1. 程式人生 > >理解PV操作和訊號量

理解PV操作和訊號量

對於訊號量,可以認為是一個倉庫,有兩個概念,容量和當前的貨物個數。

P操作從倉庫拿貨,如果倉庫中沒有貨,執行緒一直等待,直到V操作,往倉庫裡添加了貨物,為了避免P操作一直等待下去,會有一個超時時間。

V操作往倉庫送貨,如果倉庫滿了,執行緒等待,直到有P操作,從倉庫中拿走貨物,有空的位置。

建立訊號量,設定容量,先有V操作,才能P操作。

P操作:貨物個數減1,減過之後,貨物個數大於等於0,說明已經拿到貨物,執行緒繼續。否者執行緒阻塞。

V操作:貨物個數加1,加過之後,貨物個數小於等於容量,說明新增成功,執行緒繼續。否者執行緒阻塞。

訊號量:0≤ 訊號量≤容量 ,取值 表示當前可以使用的貨物;

        訊號量<0 ,  取值 表示當前等待使用貨物的執行緒;

            訊號量>容量 ,  訊號量-容量 表示當前等待新增貨物的執行緒。

通常,訊號量的容量設定很大,可以一直V操作,不會阻塞,但是P操作的時候,很可能阻塞。

當容量為1,也就是互斥,執行流程必定是V操作,P操作,V操作,P操作...

訊號量如何做到執行緒同步?

可以認為訊號量關聯一組執行緒,儲存一個指標,指向執行緒陣列的首地址。比如當前訊號量為-1,進行P操作,訊號量為-2,說明沒有拿到貨物,執行緒等待,取值為-2,說明有兩個執行緒等待那貨物。這個時候,其他執行緒進行V操作,訊號量加1,為-1,訊號量通知等待的執行緒中,第一個執行緒繼續執行,第二個執行緒繼續等待。

也就是說,P操作等待的情況是減1後,訊號量小於0。 P操作繼續執行的情況有兩種:a、減1後,訊號量大於等於0,不需等待,直接執行;b、訊號量小於0,等待中,其他人進行了V操作,通知這個執行緒,繼續執行。

專案中的使用場景:

客戶端使用提供的SDk與服務互動,為了提高效率,客戶端傳送一個請求後,SDK非同步回撥給客戶端。但是,有些請求,客戶端希望同步,等待回覆。這個時候,建立一個map,以req的sequence為key,value為訊號量的指標,訊號量的容量設定為1,可用的貨物為0,對訊號量進行TimeoutP操作,貨物個數為-1,阻塞在這裡。非同步回撥,收到回覆的sequence,根據map找到訊號量指標,進行V操作,貨物個數為0,通知前面TimeoutP的執行緒繼續執行下去,這個時候,TimeoutP的執行緒,把回覆訊息取出來,返回給客戶端。