![Python並行編程(五):多線程同步之event(事件)](http://p2.ttnews.xyz/loading.gif)
什麼是事件?
事件在內部管理了一個標誌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.\n')
# 等待事件,進入阻塞狀態
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.')
運行截圖如下:
![Python並行編程(五):多線程同步之event(事件)](http://p2.ttnews.xyz/loading.gif)
運行結果
我們可以看到,兩個消費者都在阻塞等待商品的生產,而一旦生產者通知商品生產成功(event.set() --> Flag=True),消費者們便都會得到該商品,這樣看來,event 看似就是condition的簡化版本,只是沒了鎖,線程們不能同步阻塞對共享資源的訪問。
閱讀更多 若數 的文章