什么是信號量(semaphore)
信號量(semaphore)是一個被線程共享的非負(fù)變量。信號量是一個發(fā)信號的機制。一個等待一個信號量的線程可以被其他線程通知(signal)。這個機制通過 wait 和 signal 兩個原子操作(atomic operations)來實現(xiàn)進程同步。
一個信號量要么允許訪問資源,要么不允許訪問資源。二者只能選其一。而具體是哪一種,則要看設(shè)置。
信號量的特點
下面是信號量的一些特點:
- 它是一個機制。該機制支持多任務(wù)的同時進行
- 它是一個低層級的(low-level)的同步機制
- 信號量的存儲值一直是非負(fù)的
- 信號量可以使用測試操作和中斷來實現(xiàn)。這些操作和中斷需要用文件描述符來執(zhí)行
信號量的類型
最常見的兩種信號量:
- 計數(shù)信號量(Counting semaphores)
- 二進位信號量(Binary semaphores)
計數(shù)信號量
這種信號量用一個計數(shù)來幫助任務(wù)被獲取(be acquired)或釋放(be released)數(shù)次。
- 如果起始時,計數(shù)器的計數(shù)值為0(count = 0),那么創(chuàng)建出來的信號量就應(yīng)該在不可獲得的狀態(tài)(unavailable state)。
- 如果起始時,計數(shù)器的計數(shù)值大于0(count > 0),那么創(chuàng)建出來的信號量就應(yīng)該在可獲得的狀態(tài)(available state)。而且,總共的獲取次數(shù)(tokens)就等于計數(shù)器的值。
具體機制如下圖所示:

二進位信號量
二進位信號量和計數(shù)信號量非常相似,但是他們的計數(shù)值只能限制在0和1兩個數(shù)字。在這種信號量下,等待(wait)操作只能在信號量等于1(semaphore = 1)時工作。而通知(signal)操作只有在信號量等于0(semaphore = 0)時才能成功。二進位信號量的實現(xiàn)要比計數(shù)信號量的實現(xiàn)要簡單。

信號量的等待操作和通知操作
信號量的等待操作(wait operation)和通知操作(signal operation)是用來實現(xiàn)同步的。信號量操作的不得是為了互相獨立。
等待操作(wait operation)
等待操作(wait operation)用來幫助我們控制任務(wù)是否可以進入關(guān)鍵的部分。當(dāng)信號量是正的時候,信號量將被減一。如果當(dāng)信號量為負(fù)數(shù)或者零的時候,等待操作不執(zhí)行任何操作。
當(dāng)信號量被遞減后,信號量值為負(fù)數(shù)或者零時,該指令將被掛起保持,直到信號量重新滿足大于0的條件。
function wait(S){
while ( S < 0);
S--;
}
通知操作(signal operation)
通知操作(signal operation)是用于控制一個任務(wù)退出某個重要部分。當(dāng)信號量的值是負(fù)的時候,信號量將被加一。
function signal(S){
while (S >= 0);
S++;
}
計數(shù)信號量vs二進位信號量
下面列舉了計數(shù)信號量和二進位信號量的主要不同:
| 計數(shù)信號量 | 二進位信號量 |
|---|---|
| 沒有互斥 | 互斥 |
| 任意整數(shù)值 | 只有0和1 |
| 多于一個槽(slot) | 只有一個槽(slot) |
| Provide a set of Processes | It has a mutual exclusion mechanism |