1. 程式人生 > >程序同步和執行緒同步

程序同步和執行緒同步

怎樣同步多個執行緒或多個程序的活動。為允許線上程或程序間共享資料,同步是必需的。

互斥鎖和條件變數是同步的基本組成部分。互斥鎖和條件變量出自POSIX.1執行緒標準,它們總是可用來同步一個程序內的各個執行緒的。如果一個互斥鎖或條件變數存放在多個程序間共享的某個記憶體中,那麼POSIX還允許它用於這些程序間的同步。互斥鎖、條件變數、讀寫鎖、訊號量均可用於程序、執行緒的同步。

多執行緒同步方法

1)互斥鎖
互斥鎖是最基本的同步形式,用於保護臨界區,確保同一時間只有一個執行緒或程序訪問資料或執行其中的程式碼。互斥量(mutex)本質上是一把鎖,訪問共享資源前要對互斥量加鎖,訪問完後要釋放鎖。互斥量用於上鎖,而條件變數用於等待。

允許多個程序將同一個記憶體區域對映到它們各自獨立的地址空間,就像多執行緒一樣共享資料,那麼多個程序訪問共享資料通常也需要同步。如果程序共享互斥量屬性設定為PTHREAD_PROCESS_SHARED,從多個程序共享的記憶體區域中分配的互斥量就可以用於這些程序的同步了。程序共享互斥量屬性設為PTHREAD_PROCESS_PRIVATE時,允許pthread執行緒庫提供更加有效的互斥量實現,這在多執行緒應用程式中是預設的情況。

用於給存放在共享記憶體區中供多個程序使用的條件變數設定PTHREAD_PROCESS_SHARED屬性的一組語句跟用於互斥鎖的語句幾乎相同,只需要將mutex替換為cond。

2)條件變數

條件變數與互斥量一起使用時,允許執行緒以無競爭的方式等待特定條件傳送。條件變數本身是由互斥量保護的。執行緒在改變條件狀態前必須首先鎖住互斥量,必須鎖住互斥量以後才能計算條件。如果在規定的時間內條件滿足就通知執行緒,否則生成一個代表出錯碼的返回變數。

3)讀寫鎖(共享-獨佔鎖)

和互斥鎖類似,不過讀寫鎖允許更高的並行性。互斥量要麼是鎖住狀態要麼是不加鎖狀態,而且一次僅允許一個執行緒對互斥量加鎖。

讀寫鎖有三種狀態:a. 讀模式下加鎖狀態(所有試圖以讀模式對其進行加鎖的執行緒都可以獲得訪問權,但如果試圖以寫模式加鎖,必須阻塞直到所有執行緒釋放讀鎖);b. 寫模式下加鎖狀態(在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的執行緒都會被阻塞);c. 不加鎖狀態。可用於程序、執行緒之間的同步。

4)訊號量

訊號量可用於執行緒或程序間同步。訊號量是一個計數器,用於多程序對共享資料物件的訪問。若此訊號量的值為正,則程序可以使用該資源;程序將訊號量減1,表示它使用了一個資源單元。若此訊號量的值為0,則程序進入休眠狀態,直至訊號量位於0。若一個程序不再使用由一個訊號量控制的共享資源時,該訊號量值增1。如果有程序正在休眠等待此訊號量,則喚醒它們。

程序間同步方法
上述提到的互斥鎖、條件變數、讀寫鎖、訊號量都可用於程序間同步。
互斥鎖
條件變數
讀寫鎖
訊號量
記錄鎖

Linux核心沒有檔案內的記錄這一概念。任何關於記錄的接收都是由讀寫檔案的應用來進行的。然而linux核心提供的上鎖特性卻用記錄上鎖(record locking)這一術語描述。不過應用會指定檔案中待上鎖或解鎖部分的位元組範圍,因為記錄鎖鎖定的只是檔案中的一個區域。

記錄鎖是讀寫鎖的一種拓展,可用於親緣或非親緣關係的程序間共享某個檔案的讀寫。被鎖住的檔案通過其描述符訪問,執行上鎖操作的函式是fcntl。這類鎖通常維護在核心中,其屬主是由屬主的程序ID來標識的。這意味著這些鎖用於不同程序間的上鎖,不適用於同一程序不同執行緒間上鎖。

使用fcntl記錄上鎖時,等待著的讀出者優先還是等待著的寫入者優先沒有保證;如果這對於某個應用很重要,就需要開發測試程式,或者給該應用提供滿足所需優先關係的專用讀寫鎖實現。

讀者可以參考UNIX網路程式設計卷2:程序通訊