I'm using python's Queue.Queue to synchronize several threads. First, a Queue is populated with N elements, as in
我正在使用python的Queue.Queue来同步几个线程。首先,队列中填充N个元素,如
N = 10
q = Queue.Queue()
for i in range(N):
q.put(i)
Then, several threads consume the elements from the queue with block=False
然后,几个线程使用block = False从队列中使用元素
q.get(block=False)
My question is: can the previous call to Queue.get() raise Queue.Empty in any of the first N calls?
我的问题是:先前调用Queue.get()可以在前N个调用中的任何一个中引发Queue.Empty吗?
Thanks!
1 个解决方案
#1
The first N
calls to get()
will succeed; q.get(block=False)
will only raise Queue.Empty
if the queue is actually empty. All the calls to get
made by your threads are synchronized, so the first N threads that get the mutex used by the Queue
will successfully get
an item from the Queue
. If you have N+1 or more threads, any get
beyond the Nth will raise Queue.Empty
. This is fairly easy to see for yourself by looking at the relevant parts of the Queue
code, as mentioned by Eric.
前N个调用get()将成功;如果队列实际为空,q.get(block = False)只会引发Queue.Empty。线程所做的所有调用都是同步的,因此获得Queue使用的互斥锁的前N个线程将成功从Queue获取一个项目。如果你有N + 1个或更多个线程,那么任何超过Nth的东西都会引发Queue.Empty。通过查看Eric提到的Queue代码的相关部分,可以很容易地看到这一点。
class Queue:
"""Create a queue object with a given maximum size.
If maxsize is <= 0, the queue size is infinite.
"""
def __init__(self, maxsize=0):
self.maxsize = maxsize
self._init(maxsize)
self.mutex = _threading.Lock()
self.not_empty = _threading.Condition(self.mutex)
... # Stuff we don't care about
def get(self, block=True, timeout=None):
self.not_empty.acquire() # Only on thread can hold this at a time
try:
if not block:
if not self._qsize(): # If there's nothing in the Queue
raise Empty
... # Other stuff we don't care about, since you use block=False
item = self._get()
self.not_full.notify()
return item
finally:
self.not_empty.release()
def _init(self, maxsize):
self.queue = deque()
def _qsize(self, len=len):
return len(self.queue)
#1
The first N
calls to get()
will succeed; q.get(block=False)
will only raise Queue.Empty
if the queue is actually empty. All the calls to get
made by your threads are synchronized, so the first N threads that get the mutex used by the Queue
will successfully get
an item from the Queue
. If you have N+1 or more threads, any get
beyond the Nth will raise Queue.Empty
. This is fairly easy to see for yourself by looking at the relevant parts of the Queue
code, as mentioned by Eric.
前N个调用get()将成功;如果队列实际为空,q.get(block = False)只会引发Queue.Empty。线程所做的所有调用都是同步的,因此获得Queue使用的互斥锁的前N个线程将成功从Queue获取一个项目。如果你有N + 1个或更多个线程,那么任何超过Nth的东西都会引发Queue.Empty。通过查看Eric提到的Queue代码的相关部分,可以很容易地看到这一点。
class Queue:
"""Create a queue object with a given maximum size.
If maxsize is <= 0, the queue size is infinite.
"""
def __init__(self, maxsize=0):
self.maxsize = maxsize
self._init(maxsize)
self.mutex = _threading.Lock()
self.not_empty = _threading.Condition(self.mutex)
... # Stuff we don't care about
def get(self, block=True, timeout=None):
self.not_empty.acquire() # Only on thread can hold this at a time
try:
if not block:
if not self._qsize(): # If there's nothing in the Queue
raise Empty
... # Other stuff we don't care about, since you use block=False
item = self._get()
self.not_full.notify()
return item
finally:
self.not_empty.release()
def _init(self, maxsize):
self.queue = deque()
def _qsize(self, len=len):
return len(self.queue)