Python の Event でスレッド間のシグナルを送る
Event(イベント)は、スレッド間でシンプルなシグナルを送るための同期機構です。フラグの設定とクリアだけでスレッド間の通信ができるため、Condition よりも使いやすい場面があります。
Event の基本
Event は内部にブーリアンフラグを持っています。set() でフラグを立て、clear() でフラグを下ろし、wait() でフラグが立つまで待機します。
import threading
import time
event = threading.Event()
def waiter():
print("Waiter: イベントを待機中...")
event.wait() # フラグが立つまで待機
print("Waiter: イベント受信!")
def setter():
time.sleep(2)
print("Setter: イベントを設定")
event.set() # フラグを立てる
t1 = threading.Thread(target=waiter)
t2 = threading.Thread(target=setter)
t1.start()
t2.start()
t1.join()
t2.join()Event のメソッド
set()
フラグを True にする。待機中のすべてのスレッドが起床する。
clear()
フラグを False にする。
wait(timeout=None)
フラグが True になるまで待機。タイムアウト指定可能。
is_set()
フラグの状態を確認。
wait() のタイムアウト
wait() にタイムアウトを指定すると、フラグが立たなくても指定時間後に戻ります。
import threading
event = threading.Event()
def waiter():
print("待機開始")
result = event.wait(timeout=2) # 最大2秒待つ
if result:
print("イベント受信")
else:
print("タイムアウト")
thread = threading.Thread(target=waiter)
thread.start()
thread.join()
# タイムアウト(2秒後)繰り返し使う場合は clear()
一度 set() したイベントを再利用するには、clear() でリセットする必要があります。
import threading
import time
event = threading.Event()
def worker():
for i in range(3):
event.wait() # イベントを待つ
print(f"ラウンド {i + 1} 実行")
event.clear() # 次の待機のためにリセット
def controller():
for i in range(3):
time.sleep(1)
print(f"ラウンド {i + 1} 開始を通知")
event.set()
time.sleep(0.1) # worker が処理する時間を確保
t1 = threading.Thread(target=worker)
t2 = threading.Thread(target=controller)
t1.start()
t2.start()
t1.join()
t2.join()実用例:スレッドの停止シグナル
Event はスレッドに停止を通知する際によく使われます。
import threading
import time
stop_event = threading.Event()
def worker():
while not stop_event.is_set():
print("処理中...")
time.sleep(0.5)
print("停止シグナル受信、終了します")
thread = threading.Thread(target=worker)
thread.start()
time.sleep(2)
print("停止シグナルを送信")
stop_event.set()
thread.join()実用例:初期化完了の待機
メインスレッドがワーカースレッドの初期化完了を待つパターンです。
import threading
import time
initialized = threading.Event()
def worker():
print("Worker: 初期化中...")
time.sleep(2) # 初期化処理
print("Worker: 初期化完了")
initialized.set() # 初期化完了を通知
print("Worker: メイン処理開始")
time.sleep(1)
print("Worker: メイン処理完了")
thread = threading.Thread(target=worker)
thread.start()
print("Main: Worker の初期化を待機")
initialized.wait()
print("Main: Worker の初期化完了を確認、処理を続行")
thread.join()Event と Condition の違い
Event
シンプルなフラグベース。set() ですべての待機スレッドが起床。データの受け渡しには向かない。
Condition
より柔軟。notify() で1つだけ起こすことも可能。複雑な条件での待機に対応。
単純な「準備完了」や「停止」のシグナルには Event、複雑な条件や producer-consumer パターンには Condition を使うのがおすすめです。



