一、概述
當多個線程同時訪問共享資源時,可能會發生競態條件(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-tw/n/197630.html
微信掃一掃
支付寶掃一掃