信号量

(重定向自信號標

信号量(英語: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操作會減少它。

運作方式:

  1. 初始化,給與它一個非負數的整數值。
  2. 執行P(wait()),信號標S的值將被減少。企圖進入臨界區段的行程,需要先執行P(wait())。當信號標S減為負值時,行程會被擋住,不能繼續;當信號標S不為負值時,行程可以獲准進入臨界區段。
  3. 執行V(signal()),信號標S的值會被增加。結束離開臨界區段的行程,將會執行V(signal())。當信號標S不為負值時,先前被擋住的其他行程,將可獲准進入臨界區段

Windows API提供的semaphore

线程使用CreateSemaphoreCreateSemaphoreEx函数创建一个semaphore对象[2]。此时可以指定semaphore的当前计数值与计数值上限;也可指定semaphore对象的名字。其他进程中的线程可以指出已存在的semaphore对象的名字通过调用OpenSemaphore函数打开它。

如果多个线程在等待一个semaphore对象,不保证按照先进先出(FIFO)顺序调度这些等待线程。外部事件,如内核模式的异步过程调用可改变等待顺序。

semaphore对象为signaled状态时,等待函数返回会把该semaphore对象计数值减1。函数ReleaseSemaphoresemaphore对象的计数值增加指定的值。任何线程,哪怕它没有等待完成过该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对象的线程会永久阻塞或超时返回。

参见

参考资料

  1. ^ 戴克斯特拉, 艾兹赫尔. Over de sequentialiteit van procesbeschrijvingen (EWD-74) (PDF). E·W·戴克斯特拉档案馆. 得克萨斯大学奥斯汀分校美国历史中心.  (文字版本)
  2. ^ MSDN:Semaphore Objects. [2016-09-05]. (原始内容存档于2016-09-16). 

外部連結