了解過了進程間的同步和通信,下面了解線程間的同步和通信。
相關知識點:進程和線程;信號量機制;進程同步互斥;進程間通信。
多線程OS通常提供多種同步機制。
互斥鎖(mutex)
同進程互斥類似,它實現線程間對資源的互斥訪問。
由於操作互斥鎖的時間和空間開銷都較低,因而較適合於高頻度使用的關鍵共享數據和程序段。互斥鎖有兩種狀態,即開鎖(unlock)和關鎖(lock)狀態。
當一個線程需要讀/寫共享數據段時,首先判別該共享數據段所設置的mutex 的狀態,如果它已處於關鎖狀態(不可用),則線程將被阻塞;如果 mutex 是處於開鎖狀態(可用),則將 mutex 關鎖(設置標識)后便去讀/寫該數據段。在線程完成讀/寫后,必須再發出開鎖命令將 mutex 開鎖(恢復標識),同時還須將阻塞在該互斥鎖上的一個線程喚醒,其它的線程仍被阻塞在等待 mutex 打開的隊列上。
線程對資源的互斥訪問 與 之前總結的臨界資源、臨界區一樣。
上述讀/寫共享數據段的過程相當於記錄型信號量,互斥鎖是資源,資源數為1。關鎖即資源數為0了。下圖是記錄型信號量的wait()和signal()描述,相當於互斥鎖的關鎖、開鎖。
記錄型信號量可能出現死鎖,一個進程要求臨界資源越多、死鎖可能性越大。信號量機制中有詳細總結。
線程的互斥鎖,也同樣存在可能死鎖的問題。
類似的:
有兩個線程A、B。兩個臨界資源D、E,互斥鎖分別是Dmutex、Emutex。
若A、B都需要D和E,按下面情況,無外界干預線程A、B即陷入死鎖狀態。同樣需要資源越多,線程死鎖可能也越大。
thread A: 對Dmutex關鎖成功,再對Emutex關鎖失敗(需要E,但E被線程B持有),於是A阻塞,而Dmutex一直處於關鎖狀態
thread B: 對Emutex關鎖成功,再對Dmutex關鎖失敗(需要D,但D被線程A持有),於是B阻塞,而Emutex一直處於關鎖狀態
條件變量
為了解決類似上述互斥鎖中死鎖問題引入了條件變量。
每一個條件變量通常都與一個互斥鎖一起使用,亦即,在創建一個互斥鎖時便聯系着一個條件變量。
單純的互斥鎖用於短期鎖定,主要是用來保證對臨界區的互斥進入。而條件變量則用於線程的長期等待,直至所等待的資源成為可用的資源。
利用互斥鎖和條件變量訪問資源,大致描述如下:
//定義 mutex:互斥鎖 resource:資源 condition:條件變量 ///申請過程 Lock mutex if(resource busy) wait(condition); mark resource as busy; unlock mutex; ///釋放過程 Lock mutex mark resource as free; unlock mutex; wakeup(condition);
線程先對mudex關鎖,進入臨界區。若資源忙不可用,線程變轉入等待隊列(條件變量相關的隊列),然后對mudex開鎖;若資源空閑,標記資源為忙碌,再對mudex開鎖。
使用資源的線程完成釋放資源時,mudex關鎖進入,標記資源空閑,再對mudex開鎖,然后從條件變量的隊列中喚醒一個線程。喚醒的就是之前進入等待中的線程,能夠繼續執行了。
類似管程機制中的條件變量。
信號量機制
進程同步工具:信號量機制。也可用於多線程OS中,實現多線程或進程之間的同步。
1) 私用信號量(private samephore)
當某線程需利用信號量來實現同一進程中各線程之間的同步時,可調用創建信號量的命令來創建一私用信號量。
其數據結構存放在應用程序的地址空間中。私用信號量屬於進程所有,OS並不知道私用信號量的存在。
2) 公用信號量(public semaphort)
公用信號量是為實現不同進程間各線程之間的同步而設置的。
由於它有着一個公開的名字供所有的進程使用,故而把它稱為公用信號量。其數據結構是存放在受 保護的系統存儲區中,由 OS 為它分配空間並進行管理,故也稱為系統信號量。