i am learning python's threading module and have wrote the following code to help myself understand
from Queue import Queue
import threading
lock = threading.Lock()
MAX_THREADS = 8
q = Queue()
count = 0
# some i/o process
def io_process(x):
pass
# process that deals with shared resources
def shared_resource_process(x):
pass
def func():
global q, count
while not q.empty():
x = q.get()
io_process(x)
if lock.acquire():
shared_resource_process(x)
print '%s is processing %r' %(threading.currentThread().getName(), x)
count += 1
lock.release()
def main():
global q
for i in range(40):
q.put(i)
threads = []
for i in range(MAX_THREADS):
threads.append(threading.Thread(target=func))
for t in threads:
t.start()
for t in threads:
t.join()
print 'multi-thread done.'
print count == 40
if __name__ == '__main__':
main()
and the output got stuck like this:
Thread-1 is processing 32
Thread-8 is processing 33
Thread-6 is processing 34
Thread-2 is processing 35
Thread-5 is processing 36
Thread-3 is processing 37
Thread-7 is processing 38
Thread-4 is processing 39
Note that the prints in main() is not executed which means that some threads are hanging /blocking ?
then i modify the func() method by adding q.task_done():
if lock.acquire():
shared_resource_process(x)
print '%s is processing %r' %(threading.currentThread().getName(), x)
count += 1
q.task_done() # why is this necessary ?
lock.release()
and now all threads terminates as i expected and get the right output:
Thread-6 is processing 36
Thread-4 is processing 37
Thread-3 is processing 38
Thread-7 is processing 39
multi-thread done.
True
Process finished with exit code 0
i read the doc of Queue.Queue here and see that task_done() works with queue.join() to make sure all items in queue are processed. but since i did not call queue.join() in main(), why is the task_done() necessary here in func()? What is the cause of thread hanging / blocking when i miss the task_done() code?