一、概述
當多個線程同時訪問共享資源時,可能會發生競態條件(Race Condition),導致數據不一致或程序異常崩潰等問題。而線程同步就是為了防止競態條件而採取的一些機制。Python提供了一些線程同步原語(Synchronization Primitives),用於協調線程之間的訪問。本文將介紹Python中的幾種常用線程同步原語,包括鎖、信號量、事件和條件變量。
二、鎖
鎖是最常用的線程同步機制,在Python中通過threading模塊中的Lock類來實現。在使用鎖時,一個線程獲得了鎖之後,其他線程不能再獲得該鎖,直到該線程釋放鎖為止。
import threading num = 0 # 共享變量 lock = threading.Lock() # 創建鎖對象 # 線程函數 def func(): global num for i in range(100000): lock.acquire() # 獲取鎖 num += 1 # 對共享變量進行操作 lock.release() # 釋放鎖 t1 = threading.Thread(target=func) t2 = threading.Thread(target=func) t1.start() t2.start() t1.join() t2.join() print(num) # 輸出結果為200000
三、信號量
信號量是一種比鎖更為通用的線程同步原語,在Python中通過threading模塊中的Semaphore類來實現。在使用信號量時,可以設置一個計數器,每當一個線程獲取了信號量時,計數器就會減1;而每當一個線程釋放信號量時,計數器就會加1。當計數器為0時,其他線程將被阻塞。
import threading num = 0 # 共享變量 sem = threading.Semaphore(1) # 創建信號量對象,初始值為1 # 線程函數 def func(): global num for i in range(100000): sem.acquire() # 獲取信號量 num += 1 # 對共享變量進行操作 sem.release() # 釋放信號量 t1 = threading.Thread(target=func) t2 = threading.Thread(target=func) t1.start() t2.start() t1.join() t2.join() print(num) # 輸出結果為200000
四、事件
事件是用於線程之間通信的一種機制,在Python中通過threading模塊中的Event類來實現。事件對象有一個內部的標誌位,默認為False,可以通過set()方法將其設置為True,也可以通過clear()方法將其設置為False;可以通過wait()方法來等待事件的發生。
import threading event = threading.Event() # 子線程函數 def sub_thread(): print('sub_thread: wait for event') event.wait() # 等待事件的發生 print('sub_thread: event is set') # 主線程函數 def main_thread(): print('main_thread: start') event.set() # 設置事件 print('main_thread: event is set') sub_thread() t = threading.Thread(target=main_thread) t.start() t.join()
五、條件變量
條件變量是一種更為複雜的線程同步機制,在Python中通過threading模塊中的Condition類來實現。條件變量通常與鎖一起使用,當某個條件不滿足時,該線程就會進入阻塞狀態;而當某個條件滿足時,該線程就會被喚醒。
import threading num = 0 # 共享變量 condition = threading.Condition() # 生產者線程函數 def producer(): global num for i in range(10): with condition: # 檢查條件 while num >= 5: print('producer: wait for condition') condition.wait() # 生產數據 num += 1 print('producer: produce data, num =', num) # 喚醒消費者 condition.notify() # 消費者線程函數 def consumer(): global num for i in range(10): with condition: # 檢查條件 while num <= 0: print('consumer: wait for condition') condition.wait() # 消費數據 num -= 1 print('consumer: consume data, num =', num) # 喚醒生產者 condition.notify() t1 = threading.Thread(target=producer) t2 = threading.Thread(target=consumer) t1.start() t2.start() t1.join() t2.join()
六、總結
線程同步是多線程編程中必不可少的部分,而在Python中,使用線程同步機制可以通過Lock、Semaphore、Event和Condition等幾種不同的方式來實現。我們在編寫多線程程序時,應當充分考慮線程之間的同步和通信,以確保程序的正確性。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/197630.html