The queueLock.acquire() line hangs a code that tries to take advantage of threading and Queue modules with following output:
run() on <newThread(Thread-1, started 4344102912)>
run() on <newThread(Thread-2, started 4348309504)>
...working delay: 1
Why?
import threading, thread, Queue, time
class newThread (threading.Thread):
def __init__(self, delay=0, workQueue=None):
self.delay=delay
self.workQueue=workQueue
threading.Thread.__init__(self)
def run(self):
print '\nrun() on %s'%self
print_time(self.delay, self.workQueue)
print '\nrun() exit %s'%self
def print_time(delay=None, workQueue=None):
def onExit():
if not workQueue.empty():
data = workQueue.get()
queueLock.release()
else:
queueLock.release()
counter=0
while True:
queueLock.acquire()
time.sleep(delay)
print '\t...working delay: %s'%delay
if counter>5:
onExit()
counter=counter + 1
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
thread1 = newThread(delay=1, workQueue=workQueue)
thread1.start()
threads.append(thread1)
thread2 = newThread(delay=2, workQueue=workQueue)
thread2.start()
threads.append(thread2)
queueLock.acquire()
print '1. workQueue.empty():',workQueue.empty()
workQueue.put('One')
print '2. workQueue.empty():',workQueue.empty()
workQueue.put('Two')
queueLock.release()
#Wait for queue to empty
while not workQueue.empty():
print '...passing while not workQueue.empty()'
pass
for thread in threads:
thread.join()
print '...completed'
asked Oct 11, 2015 at 2:07
alphanumeric
19.6k74 gold badges280 silver badges426 bronze badges
1 Answer 1
queueLock.acquire() blocks until queueLock.release() is called if queueLock is already acquired. counter > 5 never happens because even if queueLock is available on the first iteration of the loop; nothing releases it on the 2nd iteration.
Queue() has its own locks. Drop queueLock completely.
answered Oct 11, 2015 at 4:30
jfs
417k211 gold badges1k silver badges1.7k bronze badges
Sign up to request clarification or add additional context in comments.
1 Comment
Ulrich Eckhardt
I'd like to add that in order to not forget releasing a lock, you can use it as context manager, i.e.
with some_lock.acquire(): ....lang-py
printlines actually executed)Thread, you can simply run any function with a plainThreadinstance. It would also help if you didn't specify default parameters for functions where they may no sense at all, like passingNoneas queue toprint_time(). Also, upgrade to Python 3!Threadinstance.