操作系統之進程同步

1. 同步

協調多線程對共享數據的訪問,任何時刻只能有一個線程執行臨界區代碼。

2. 臨界區

定義:對共享內存進行訪問的程序片段。
實現方法

  • 禁用中斷:沒有中斷,沒有上下文切換,因此沒有併發。
  • 軟件方法:如 Peterson 算法。複雜、需要兩個進程間的共享數據項;需要忙等待,浪費 CPU 時間
  • 更高級的抽象方法:硬件提供了一些同步原語,操作系統提供更高級的編程抽象來簡化進程同步。如鎖。

3. 信號量(semaphore)

信號量是操作系統提供的一種協調共享資源訪問的方法,用信號量表示系統資源的數量。

一種抽象的數據類型,由一個整型變量(sem)和兩個原子操作組成,操作系統保證 PV 操作的原子性。

  • P()(嘗試減少):sem 減 1,如 sem < 0,進入等待,否則繼續
  • V()(增加):sem 加 1,如 sem <= 0,喚醒一個等待線程

3.1 信號量實現互斥訪問

在這裏插入圖片描述

3.2 信號量實現同步等待

在這裏插入圖片描述

3.3 信號量實現生產者消費者問題

問題抽象:

  1. 任何時刻只能有一個線程操作緩衝區(互斥訪問)
  2. 緩衝區空時,消費者必須等待生產者(條件同步)
  3. 緩衝區滿時,生產者必須等待消費者(條件同步)

用信號量描述每個約束:

  1. 二進制信號量 mutex
  2. 資源信號量 fullBuffers
  3. 資源信號量 emptyBuffers

代碼:
在這裏插入圖片描述

4. 管程

一種用於多線程互斥訪問共享資源的程序結構。任意時刻最多隻有一個線程執行管程代碼,正在管程中的線程可臨時放棄管程的互斥訪問,等待事件出現時恢復。

組成

  1. 一個鎖:控制管程代碼的互斥訪問;
  2. 0 個或多個條件變量:管理共享數據的併發訪問。條件變量是管程內的等待機制,每個條件變量表示一種等待原因,對應一個等待隊列。Wait() 操作:將自己阻塞在等待隊列中,喚醒一個等待者或釋放管程的互斥訪問。Signal() 操作:將等待隊列中的一個線程喚醒。

管程解決生產者消費者問題
在這裏插入圖片描述

5. 經典同步問題之哲學家就餐問題

在這裏插入圖片描述
五個哲學家圍着一張圓桌,每個哲學家面前放着食物。哲學家的生活有兩種交替活動:吃飯以及思考。當一個哲學家吃飯時,需要先拿起自己左右兩邊的兩根筷子,並且一次只能拿起一根筷子。思考時將兩支叉子放回原處。如何保證哲學家們的動作有序進行?不會出現有人永遠拿不到叉子。

使用信號量解決:
在這裏插入圖片描述
根據哲學家不同編號,使其拿起兩隻筷子的順序不同,避免五個哲學家都拿到一部分資源構成環路的情況。

6. 讀者-寫者問題

對共享數據的讀寫,同一時刻,允許有多個讀者同時讀;沒有讀者時寫者才能寫,沒有寫着時讀者才能讀;沒有其他寫者時才能寫。

使用信號量解決:
在這裏插入圖片描述
讀者優先策略:只要有讀者正在讀狀態,後來的讀者都能直接進入,如讀者持續不斷進入,則寫者就處於飢餓狀態。
在這裏插入圖片描述
寫者優先策略:只要有寫者就緒,寫者應儘快執行寫操作;如寫者持續不斷進入,則讀者就處於飢餓狀態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章