天天看點

程序同步和線程同步

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

互斥鎖和條件變量是同步的基本組成部分。互斥鎖和條件變量出自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:程序通信

繼續閱讀