一、同步與互斥
????????在線程并發執行的過程中,進程/線程之間存在協作的關系,例如有互斥、同步的關系。為了實現進程/線程間正確的協作,操作系統必須提供實現進程協作的措施和方法,主要的方法有兩種:
- 鎖:加鎖、解鎖操作;
- 信號量:P、V 操作;
1. 鎖
????????使用加鎖操作和解鎖操作可以解決并發線程/進程的互斥問題。任何想進入臨界區的線程,必須先執行加鎖操作。若加鎖操作順利通過,則線程可進入臨界區;在完成對臨界資源的訪問后再執行解鎖操作,以釋放該臨界資源。
【面試八股總結】鎖:互斥鎖、自旋鎖、讀寫鎖、樂觀鎖、悲觀鎖-CSDN博客https://blog.csdn.net/rabbit_qi/article/details/139455231?spm=1001.2014.3001.5501
2. 信號量
????????信號量是操作系統提供的一種協調共享資源訪問的方法。通常信號量表示資源的數量,對應的變量是一個整型(sem
)變量。另外,還有兩個原子操作的系統調用函數來控制信號量的,分別是:
- P 操作:將?
sem
?減?1
,相減后,如果?sem < 0
,則進程/線程進入阻塞等待,否則繼續,表明 P 操作可能會阻塞; - V 操作:將?
sem
?加?1
,相加后,如果?sem <= 0
,喚醒一個等待中的進程/線程,表明 V 操作不會阻塞;
P 操作是用在進入臨界區之前,V 操作是用在離開臨界區之后,這兩個操作是必須成對出現的。
二、經典問題
1.?哲學家就餐問題
問題描述:
5
?個哲學家,圍繞著一張圓桌吃面;- 桌子只有?
5
?支叉子,每兩個哲學家之間放一支叉子; - 哲學家圍在一起先思考,思考中途餓了就會想進餐;
- 這些哲學家要兩支叉子才愿意吃面,也就是需要拿到左右兩邊的叉子才進餐;
- 吃完后,會把兩支叉子放回原處,繼續思考;
如何保證哲學家們的動作有序進行,而不會出現有人永遠拿不到叉子呢?
2.?讀者-寫者問題
問題描述:
讀者只會讀取數據,不會修改數據,而寫者即可以讀也可以修改數據。
- 「讀-讀」允許:同一時刻,允許多個讀者同時讀
- 「讀-寫」互斥:沒有寫者時讀者才能讀,沒有讀者時寫者才能寫
- 「寫-寫」互斥:沒有其他寫者時,寫者才能寫
3. 生產者-消費者問題
問題描述:
- 生產者在生成數據后,放在一個緩沖區中;
- 消費者從緩沖區取出數據處理;
- 任何時刻,只能有一個生產者或消費者可以訪問緩沖區;
分析問題得出:
- 任何時刻只能有一個線程操作緩沖區,說明操作緩沖區是臨界代碼,需要互斥;
- 緩沖區空時,消費者必須等待生產者生成數據;
- 緩沖區滿時,生產者必須等待消費者取出數據,說明生產者和消費者需要同步。
需要三個信號量,分別是:
- 互斥信號量?
mutex
:用于互斥訪問緩沖區,初始化值為 1; - 資源信號量?
fullBuffers
:用于消費者詢問緩沖區是否有數據,有數據則讀取數據,初始化值為 0(表明緩沖區一開始為空); - 資源信號量?
emptyBuffers
:用于生產者詢問緩沖區是否有空位,有空位則生成數據,初始化值為 n (緩沖區大小);