Trong khi kiểm tra kỹ lưỡng rằng threading.Condition
được vá đúng cách, tôi nhận thấy rằng một con khỉ threading.Thread(…).start()
hoạt động khác với gevent.spawn(…)
.Tại sao `gevent.spawn` khác với` sreading.Thread() `của monkeypatched?
xem xét:
from gevent import monkey; monkey.patch_all()
from threading import Thread, Condition
import gevent
cv = Condition()
def wait_on_cv(x):
cv.acquire()
cv.wait()
print "Here:", x
cv.release()
# XXX: This code yields "This operation would block forever" when joining the first thread
threads = [ gevent.spawn(wait_on_cv, x) for x in range(10) ]
"""
# XXX: This code, which seems semantically similar, works correctly
threads = [ Thread(target=wait_on_cv, args=(x,)) for x in range(10) ]
for t in threads:
t.start()
"""
cv.acquire()
cv.notify_all()
print "Notified!"
cv.release()
for x, thread in enumerate(threads):
print "Joining", x
thread.join()
Lưu ý, đặc biệt, hai bình luận bắt đầu với XXX
.
Khi sử dụng dòng đầu tiên (với gevent.spawn
), các thread.join()
đầu tiên đặt ra một ngoại lệ:
Notified! Joining 0 Traceback (most recent call last): File "foo.py", line 30, in thread.join() File "…/gevent/greenlet.py", line 291, in join result = self.parent.switch() File "…/gevent/hub.py", line 381, in switch return greenlet.switch(self) gevent.hub.LoopExit: This operation would block forever
Tuy nhiên, Thread(…).start()
(khối thứ hai), mọi thứ hoạt động như mong đợi.
Tại sao điều này là? Sự khác biệt giữa gevent.spawn()
và Thread(…).start()
là gì?