正しくモンキー パッチが適用されていることを再確認しているときに、モンキー パッチが適用されたものとは動作が異なる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()
具体的には、 で始まる 2 つのコメントに注意してくださいXXX
。
最初の行 ( を使用gevent.spawn
)を使用すると、最初の行thread.join()
で例外が発生します。
通知されました! 参加中 0 トレースバック (最新の呼び出しが最後): ファイル「foo.py」の 30 行目 スレッド.結合() ファイル「…/gevent/greenlet.py」、291行目、結合 結果 = self.parent.switch() ファイル「…/gevent/hub.py」、381行目、スイッチ greenlet.switch(self) を返す gevent.hub.LoopExit: この操作は永久にブロックされます
ただし、Thread(…).start()
(2 番目のブロック)、すべてが期待どおりに機能します。
これはなぜでしょうか?gevent.spawn()
とはどう違いThread(…).start()
ますか?