這些內容主要是用來控制在併發過程中,執行緒的同步行為的。
lock
是在控制同步中 常見且基礎的物件。通過這個物件可以控制共享資源的序列訪問。
需要注意: 鎖的獲取、釋放, 防止死鎖!
from threading import lock
lock = lock(
)with lock:
pass
當然可以新增兩個引數,blocking
,timeout
用來控制怎麼獲取鎖。
可以阻塞, 可以超時,預設是阻塞無超時,就是一直等待下去。
預設引數:timeout=-1, blocking=true
重入鎖。
為什麼會出現:當時用普通的鎖的時候,如果已經獲取了鎖,再次獲取的時候,就會永久阻塞。也就是鎖不會被釋放
也不能再次被獲取。這就造成了死鎖。
解決方式:就是提供了乙個型別的鎖,重入鎖,rlock
特點:就是已經獲取到鎖後當前執行緒可以再次獲取。
內部實現: 基本鎖是lock
, 內部是通過獲取當前鎖的持有人的id
, 每次獲取的時候進行判斷,是同乙個就返回並給計數加1。
釋放則不會直接把鎖釋放掉,而是計數減一,直到計數為0,才真正的釋放屌內部鎖
from threading import rlock
r_lock = rlock(
)with r_lock:
print
(r_lock)
with r_lock:
print
(r_lock)
輸出:
可看到count
變為了2,owner
表示持有人為5832
條件,條件變數, 狀態
為什麼會出現: 假如有乙個需求 是在某些順序**中 要不止一次
的控制暫停等待
或者喚醒
。
如果單單的只是用一把普通的鎖,多個任務(併發的同樣的任務或是同時執行的不同的任務)也就只能停止等待一次,獲取了鎖,執行完就釋放了。
那麼如果要多次等待幾次,那就同時多整幾把鎖,放到佇列裡面, 並且不同的併發的執行緒中的等待的鎖不能一樣。但是可以通過介面釋放這些鎖,達到喚醒目的。
同時,因為處於併發環境下,協調這些鎖的時候為了避免鎖佇列內容不同步,需要有一把序列鎖,保證協調的時候序列執行。同時也是防止等待超時之後直接順序執行**
怎麼實現呢:
材料: 同步鎖,鎖佇列
實現方式: 在需要等待的時候,先保證持有同步鎖,生成一把普通的鎖,加進鎖佇列,然後進行等待,同時釋放轉儲同步鎖,讓其他執行緒使用。
同時要注意鎖佇列的清除,把超時的鎖清除,和被喚醒的鎖清除。清除完畢之後要重新獲取同步鎖,防止因阻塞鎖超時釋放而自動執行**
通知介面: 通知介面會將所有的阻塞鎖進行釋放,讓等待這些鎖的斷點進行執行。
需要注意的是:
在使用wait
,notify
的時候要先獲取同步鎖。
不關鍵的關鍵內容:wait
裡面是怎麼通過一把鎖使得當前執行緒暫停的。
基本方式如下:
is_block =
true
timeout =
3from threading import lock
lock_queue =
******_lock = lock(
)******_lock.acquire(
)# 釋放同步鎖,讓其他執行緒使用
******_lock.acquire(block=is_block, timeout=timeout)
# 這樣 這個順序**就被阻塞到這個地方了
其中這個******_lock 就是用來阻斷**執行,只有等到 ******_lock 被其他執行緒釋放,或是超時才能繼續往下執行**。
另外,超時之後,還要爭用同步鎖。
訊號量相對於普通的鎖,增加了併發控制,可以認為的控制同時執行的執行緒個數
內部實現基於condition
事件裡面增加了標記,被稱為事件訊號,是condition的又一包裝。 當標記被設定之後,喚醒所有等待事件訊號的執行緒。
操作相對condition更加簡單
內部實現:condition
執行緒同步中的鎖和訊號量
由於工作上用到執行緒之間的同步,而且有超時處理,問題是 子主線程等待的時候已經加鎖了,為什麼主線程中還可以再去加鎖給子執行緒傳送訊號呢?pthread cond timedwait 函式有三個入口引數 pthread cond t cond 條件變數 觸發條件 pthread mutex t mut...
執行緒同步的方法 互斥鎖 訊號量和條件變數
在說執行緒的同步非同步之前,先說一下程序的同步與非同步,因為執行緒的同步與非同步基本上是乙個概念,只是將程序之間的關係修改為執行緒之間的關係 1 同步 當乙個程序 執行緒在執行某個請求的時候,請求的資訊需要等一段時間才能夠返回,那麼該程序 執行緒就一直等待,直到請求的資訊返回。2 非同步 當乙個程序...
執行緒同步 條件變數和訊號量
上一節提到了執行緒互斥和同步的概念,並且給出了兩種用於解決共享資源互斥的利器 互斥鎖和讀寫鎖。那麼本節將介紹兩種用於解決執行緒同步的概念 條件變數和訊號量。一.條件變數 1.基本概念 互斥鎖的缺點是它只有兩種狀態 鎖定和非鎖定。而條件變數通過允許執行緒阻塞和等待另乙個執行緒傳送訊號的方法彌補了互斥鎖...