訊號量(英語:semaphore)又稱為訊號標,是一個同步對象,用於保持在0至指定最大值之間的一個計數值。當執行緒完成一次對該semaphore對象的等待(wait)時,該計數值減一;當執行緒完成一次對semaphore對象的釋放(release)時,計數值加一。當計數值為0,則執行緒等待該semaphore對象不再能成功直至該semaphore對象變成signaled狀態。semaphore對象的計數值大於0,為signaled狀態;計數值等於0,為nonsignaled狀態。
訊號量的概念是由荷蘭電腦科學家艾茲赫爾·戴克斯特拉(Edsger W. Dijkstra)發明的[1],廣泛的應用於不同的作業系統中。在系統中,給予每一個行程一個訊號量,代表每個行程目前的狀態,未得到控制權的行程會在特定地方被強迫停下來,等待可以繼續進行的訊號到來。如果訊號量是一個任意的整數,通常被稱為計數訊號量(Counting semaphore),或一般訊號量(general semaphore);如果訊號量只有二進位的0或1,稱為二進位訊號量(binary semaphore)。
語法
計數訊號量具備兩種操作動作,稱為V(signal()
)與P(wait()
)(即部分參考書常稱的「PV操作」)。V操作會增加訊號標S的數值,P操作會減少它。
運作方式:
Windows API提供的semaphore
執行緒使用CreateSemaphore或CreateSemaphoreEx函數建立一個semaphore對象[2]。此時可以指定semaphore的當前計數值與計數值上限;也可指定semaphore對象的名字。其他行程中的執行緒可以指出已存在的semaphore對象的名字通過呼叫OpenSemaphore函數打開它。
如果多個執行緒在等待一個semaphore對象,不保證按照先進先出(FIFO)順序排程這些等待執行緒。外部事件,如內核模式的非同步過程呼叫可改變等待順序。
在semaphore對象為signaled狀態時,等待函數返回會把該semaphore對象計數值減1。函數ReleaseSemaphore把semaphore對象的計數值增加指定的值。任何執行緒,哪怕它沒有等待完成過該semaphore對象,也可以使用ReleaseSemaphore來增加semaphore對象的計數。如果ReleaseSemaphore導致對象計數值超過上限,則該函數呼叫失敗,返回298號錯誤:「Too many posts were made to a semaphore」。
一個執行緒多次等待同一個semaphore對象,每次等待操作完成都會降低semaphore對象計數值(直至計數值為0時該執行緒阻塞)。然而,通過multiple-object等待函數使用一個陣列包含着同一個semaphore對象的多個控制代碼,不能實現對這個semaphore對象計數值的多次下降。
用完semaphore對象後,呼叫CloseHandle函數關閉它。semaphore對象的最後一個控制代碼被關閉後,作業系統會摧毀它。關閉semaphore並不影響它的計數值。因此,關閉semaphore前或者行程終止前,要確保已經正確呼叫過ReleaseSemaphore。否則,掛起等待該semaphore對象的執行緒會永久阻塞或逾時返回。