在仔细检查threading.Condition
猴子补丁是否正确时,我注意到猴子补丁的threading.Thread(…).start()
行为与gevent.spawn(…)
.
考虑:
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()
请特别注意,以 . 开头的两条注释XXX
。
使用第一行 (with gevent.spawn
) 时,第一行thread.join()
会引发异常:
通知! 加入 0 回溯(最近一次通话最后): 文件“foo.py”,第 30 行,在 线程.join() 文件“…/gevent/greenlet.py”,第 291 行,加入 结果 = self.parent.switch() 文件“…/gevent/hub.py”,第 381 行,在交换机中 返回 greenlet.switch(self) gevent.hub.LoopExit:此操作将永远阻塞
但是,Thread(…).start()
(第二个块),一切都按预期工作。
为什么会这样?gevent.spawn()
和有什么区别Thread(…).start()
?