Python並行編程(五):多線程同步之event(事件)

Python並行編程(五):多線程同步之event(事件)

什麼是事件?

事件在內部管理了一個標誌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(事件)

運行結果

我們可以看到,兩個消費者都在阻塞等待商品的生產,而一旦生產者通知商品生產成功(event.set() --> Flag=True),消費者們便都會得到該商品,這樣看來,event 看似就是condition的簡化版本,只是沒了鎖,線程們不能同步阻塞對共享資源的訪問。


分享到:


相關文章: