1. 程式人生 > >程序/執行緒同步、互斥、通訊的問題:

程序/執行緒同步、互斥、通訊的問題:

最近也是遇到很多程序、執行緒同步、互斥,程序間通訊的問題,這些問題放在一起很容易引起混淆,最近也查閱了相關的書籍資料和一些部落格,在此寫出自己的一些相關總結,希望對大家有幫助。

首先要說的是程序、執行緒兩種最基本的關係:競爭關係和協作關係
程序的互斥、同步、通訊都是基於這兩種基本關係而存在的:
1.為了解決程序間競爭關係(間接制約關係)而引入程序互斥;
2.為了解決程序間鬆散的協作關係( 直接制約關係)而引入程序同步;
3.為了解決程序間緊密的協作關係而引入程序通訊

定義(以程序為例):
程序互斥:指若干個程序要使用同一共享資源時,任何時刻最多允許一個程序去使用,其他要使用該資源的程序必須等待,直到佔有資源的程序釋放該資源。
程序的同步:是解決程序間協作關係( 直接制約關係) 的手段。程序同步指兩個以上程序基於某個條件來協調它們的活動。一個程序的執行依賴於另一個協作程序的訊息或訊號,當一個程序沒有得到來自於另一個程序的訊息或訊號時則需等待,直到訊息或訊號到達才被喚醒
程序通訊:程序之間互相交換資訊的工作稱之為程序通訊IPC (InterProcess Communication),多個程序之間相互通訊,交換資訊傳遞資料的方法

接下來分別說一下各部分:

程序同步:
不同的作業系統下程序同步的方式不同:
Linux 下:
Linux 下常見的程序同步方法有:SysVIPC 的 sem(訊號量)、file locking / record locking(通過 fcntl 設定的檔案鎖、記錄鎖)、futex(基於共享記憶體的快速使用者態互斥鎖)。針對執行緒(pthread)的還有 pthread_mutex 和 pthread_cond(條件變數)。

Windows下:
在Windwos中,程序同步主要有以下幾種:互斥量、訊號量、事件、可等計時器等幾種技術。

在Windows下,程序通訊主要有以下幾種:記憶體對映、管道、訊息等,但是記憶體對映是最基礎的,因為,其他的程序通訊手段在內部都是考記憶體對映來完成的

以上所說的是程序的同步方式,接下來介紹執行緒常見的同步方式,這也是程序常見的同步方式:

執行緒間的同步方式:常見的同步機制主要是:臨界區、互斥區、事件、訊號量這四種

臨界區:
臨界區對應著一個CcriticalSection物件,當執行緒需要訪問保護資料時,呼叫EnterCriticalSection函式;當對保護資料的操作完成之後,呼叫LeaveCriticalSection函式釋放對臨界區物件的擁有權,以使另一個執行緒可以奪取臨界區物件並訪問受保護的資料。
PS:關鍵段物件會記錄擁有該物件的執行緒控制代碼即其具有“執行緒所有權”概念,即進入程式碼段的執行緒在leave之前,可以重複進入關鍵程式碼區域。所以關鍵段可以用於執行緒間的互斥,但不可以用於同步(同步需要在一個執行緒進入,在另一個執行緒leave)

互斥量:
互斥與臨界區很相似,但是使用時相對複雜一些(互斥量為核心物件),不僅可以在同一應用程式的執行緒間實現同步,還可以在不同的程序間實現同步,從而實現資源的安全共享。

訊號量:
訊號量的用法和互斥的用法很相似,不同的是它可以同一時刻允許多個執行緒訪問同一個資源,PV操作

事件:
事件分為手動置位事件和自動置位事件。事件Event內部它包含一個使用計數(所有核心物件都有),一個布林值表示是手動置位事件還是自動置位事件,另一個布林值用來表示事件有無觸發。由SetEvent()來觸發,由ResetEvent()來設成未觸發。

注:訊號量是程序同步與互斥的常用方法,也可以作為低階的程序通訊方法

接下來說一下程序間的通訊方式:

程序同信:
根據程序通訊時資訊量大小的不同,可以將程序通訊劃分為兩大型別:
1、低階通訊,控制資訊的通訊(主要用於程序之間的同步,互斥,終止和掛起等等控制資訊的傳遞)
2、高階通訊,大批資料資訊的通訊(主要用於程序間資料塊資料的交換和共享,常見的高階通訊有管道,訊息佇列,共享記憶體等).

程序通訊的具體方式:
1.管道( pipe ):管道是一種半雙工的通訊方式,資料只能單向流動,提供的共享檔案通訊機制
2.有名管道 (named pipe) : 有名管道也是半雙工的通訊方式
3.訊號量( semophore ) : 訊號量是一個計數器,可以用來控制多個程序對共享資源的訪問。不是用於交換大批資料,而用於多執行緒之間的同 步.常作為一種鎖機制,防止某程序在訪問資源時其它程序也訪問該資源。
4.訊息佇列( message queue ) : 訊息佇列是由訊息的連結串列,存放在核心中並由訊息佇列識別符號標識。
5.訊號 ( signal ) : 訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生。
6.共享記憶體( shared memory ):共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以訪問。
7.套接字( socket ) : 套解口也是一種程序間通訊機制,與其他通訊機制不同的是,它可用於不同機器間的程序通訊。

注:管道與管程是不同的,管程是程序同步的方式,而管道則是程序通訊的方式

這裡再簡單介紹一下執行緒通訊的三種方式:
執行緒間通訊:
1.使用全域性變數
主要由於多個執行緒可能更改全域性變數,因此全域性變數最好宣告為violate
2.使用訊息實現通訊
在Windows程式設計中,每一個執行緒都可以擁有自己的訊息佇列(UI執行緒預設自帶訊息佇列和訊息迴圈,工作執行緒需要手動實現訊息迴圈),因此可以採用訊息進行執行緒間通訊
3.使用事件CEvent類實現執行緒間通訊
Event物件有兩種狀態:有訊號和無訊號,執行緒可以監視處於有訊號狀態的事件,以便在適當的時候執行對事件的操作。

綜上所述:程序互斥、同步與通訊的關係:互斥是一種特殊的同步,程序同步是一種程序通訊,由此看來,程序互斥、同步都可以看做程序的通訊

希望大家有什麼自己的看法可以留言一起進行討論,謝謝