第38條 執行緒中使用Lock來防止資料競爭

2021-10-03 06:58:14 字數 2181 閱讀 6997

python在內建的threading模組中提供了lock類,該類相當於互斥鎖,可以保護各執行緒資料結構不被破壞。

案例:新建乙個counter類,統計感測器取樣獲得的樣本數量。

### 計數器

class

counter

(object):

def__init__

(self)

: self.count =

0def

increment

(self,offset)

: self.count += offset

### 感測器

defwoker

(sensor_index,how_many,counter)

:for _ in

range

(how_many)

:## read from the sensor

##....

counter.increment(1)

#### run_threads函式

defrun_threads

(func,how_many,counter)

: threads =

for i in

range(5

):args =

(i,how_many,counter)

thread = thread(target=func,args = args)

thread.start(

)for thread in threads:

thread.joint(

)if __name__==

'__main__'

:###執行

how_many =

10**

5 counter = counter(

) run_threads(worker,how_many,counter)

print(5

*how_many,counter.count)

輸出結果:

500000

278328

可以看出,兩者資料相差較大,這是由於程式在執行self.count += offset語句時,並非原子操作,而是可以分解為:

value =

getattr

(counter,

'count'

)result = value + offset

setattr

(counter,

'count'

,result)

上述三個操作,在任意兩個操作之間都可能發生執行緒切換,這種頻繁的執行緒切換,交錯執行可能會令執行緒把舊的value設定給counter

因此,在不加鎖的前提下,允許多條執行緒修改同一物件,那麼程式的資料結構可能會遭到破壞。

我們可以用互斥鎖保護counter物件,使得多個執行緒同時訪問value值的時候,不會將該值破壞。同一時刻,只有乙個執行緒能夠獲得這把鎖。如下:

class

lockingcounter

(object):

def__init__

(self)

: self.lock = lock(

) self.count =

0def

increment

(self,offset)

:with self.lock:

###判斷鎖狀態

self.count += offset

if __name__ ==

'__main__'

: counter = lockingcounter(

) run_threads(worker,how_many,counter)

print(5

*how_many,counter.count)

基本執行緒同步 在Lock中使用多個條件

在lock中使用多個條件 乙個鎖可能伴隨著多個條件。這些條件宣告在condition介面中。這些條件的目的是允許執行緒擁有鎖的控制並且檢查條件是否為true,如果是false,那麼執行緒將被阻塞,直到其他執行緒喚醒它們。condition介面提供一種機制,阻塞乙個執行緒和喚醒乙個被阻塞的執行緒。在併...

使用Lock解決執行緒安全問題

lock介面的概述 lock是jdk1.5 新特性 專門用來實現執行緒安全的技術 lock介面的常用實現類 reentrantlock 互斥鎖 lock介面的常用方法 void lock 獲取鎖 void unlock 釋放鎖 注意事項 獲取鎖和釋放鎖的 必須成對出現。public class ti...

C 多執行緒Lock鎖定的使用例子 多執行緒執行緒同步)

這個例子是乙個模擬多個人在多台提款機上同時提取乙個賬戶的款的情況。在訪問的過程中 可能 a執行緒取了100 而b執行緒那邊還看見賬戶上沒少掉那100快,所以導致資料不統一,賦值出現問題。下面 則可以測試出加上lock鎖定 與 不加的區別。先上兩個圖。第乙個 加了lock的程式 加了的 資料每一條都是...