什麼是事件?
事件在內部管理了一個標誌Flag
,如果Flag
值為 False
,那麼執行緒在執行event.wait
方法時就會阻塞等值直到Flag值為True
,該執行緒便會順利執行,而Flag
的值是通過event.set()
和event.clear()
設定的:
-
set(): 將標誌設為
True
,並通知所有處於等待阻塞狀態的執行緒恢復執行狀態。 -
clear(): 將標誌設為
False
。 -
wait(timeout): 如果標誌為
True
將立即返回,否則阻塞執行緒至等待阻塞狀態,等待其他執行緒呼叫set()
。 -
isSet(): 獲取內建標誌狀態,返回
True
或False
。
而Event其實就是一個簡化版的 Condition。Event沒有鎖,無法使執行緒進入同步阻塞狀態,所以當個多個執行緒處於wait
狀態時,一旦標誌位Flag
變為真時,這些執行緒便會 “同時” (GIL鎖的原因,假裝在同時執行)執行。
簡單的生產者-消費者模型
通過事件,我們也可以實現一個簡單的生產者-消費者模型:
import threading
import random
import time
# 假定商品序號
goods = 0
# 定義一個事件
event = threading.Event()
def consumer():
time.sleep(0.5)
print(threading.currentThread().getName() + ' consumer is wait for goods.')
# 等待事件,進入阻塞狀態
event.wait()
print(threading.currentThread().getName() + ' consumer gets the goods: {}\n'.format(goods))
def producer():
global goods
time.sleep(1)
goods = random.randint(1, 11)
print('producer makes the goods: {}\n'.format(goods))
time.sleep(1)
# Flag --> True
event.set()
if __name__ == "__main__":
thread_consumer1 = threading.Thread(target=consumer)
thread_consumer2 = threading.Thread(target=consumer)
thread_producer = threading.Thread(target=producer)
thread_consumer1.start()
thread_consumer2.start()
thread_producer.start()
thread_consumer1.join()
thread_consumer2.join()
thread_producer.join()
print('consumer-producer example end.')
複製程式碼
執行截圖如下:
我們可以看到,兩個消費者都在阻塞等待商品的生產,而一旦生產者通知商品生產成功(event.set()
--> Flag=True
),消費者們便都會得到該商品,這樣看來,event 看似就是condition的簡化版本,只是沒了鎖,執行緒們不能同步阻塞對共享資源的訪問。