1. 程式人生 > >The Little Book of Semaphores 訊號量小書 第二章 訊號量

The Little Book of Semaphores 訊號量小書 第二章 訊號量

第二章 訊號量

在現實生活中,訊號量是用於視覺通訊的訊號系統,通常具有標誌,燈或一些其他機制。 在軟體中,訊號量是一種資料結構,可用於解決各種同步問題。

訊號量是由著名的“古怪”的電腦科學家Edsger Dijkstra發明的。 自最初的設計以來,一些細節已經改變,但基本思路是一樣的。

2.1 定義

訊號量就像一個整數,但有以下三個不同之處:

  1. 建立訊號量時,可以將其值初始化為任何整數,但在此之後,您可以執行的唯一操作是遞增(增加1)和遞減(減少1)。 您無法讀取訊號量的當前值。
  2. 當執行緒遞減訊號量時,如果結果為負,則執行緒會阻塞自身並且無法繼續,直到另一個執行緒遞增訊號量。
  3. 當執行緒遞增訊號量時,如果有其他執行緒在等待,則其中一個等待執行緒將被解除阻塞。

要說執行緒阻塞自身(或簡稱為“阻塞”)就是說它通知排程程式它不能繼續執行。 排程程式將阻止該執行緒執行,直到發生導致執行緒解除阻塞的事件。 在電腦科學中混合隱喻的傳統中,解除阻塞通常被稱為“喚醒”。

這就是定義的全部內容,但是,關於這個定義,還有一些重要的內容是您需要了解的。

  • 通常,線上程遞減訊號量之前無法知道它是否會阻塞(在特定情況下,您可能能夠確定它會或不會)。
  • 一個執行緒增加一個訊號量並且另一個執行緒被喚醒後,兩個執行緒繼續併發執行。 沒有辦法知道是哪個執行緒(如果有的話)會立即繼續執行。
  • 當您傳送訊號量時,您不一定知道另一個執行緒是否在等待,因此未阻塞執行緒的數量可能為零或一。

最後,您可能想要考慮訊號量的值有什麼含義。 如果值為正,則表示可以在不阻塞的情況下遞減的執行緒數。 如果是負數,則表示已阻塞且正在等待的執行緒數。 如果值為零,則表示沒有執行緒在等待,但如果執行緒嘗試遞減,則它將阻塞。

2.2 語法

在大多數程式設計環境中,訊號量的實現可作為程式語言或作業系統的一部分。 不同的實現有時提供稍微不同的功能,並且通常需要不同的語法。

在本書中,我將使用一種簡單的偽語言來演示訊號量的工作原理。建立新的訊號量並對其初始化的語法是:

                訊號量初始化語法

函式Semaphore是一個建構函式;它建立並返回一個新的訊號量。 訊號量的初始值作為引數傳遞給建構函式。

訊號量操作在不同的環境中使用不同的名稱。 最常見的替代方案有:

               訊號量操作

以及:

還有:

令人驚訝的是,有這麼多名字,但這是有原因的。 increment(遞增)和decrement(遞減)描述是如何操作的。 signal(訊號)和wait(等待)描述它們要做什麼。 V和P是Dijkstra提出的原始名稱,他明智地意識到無意義的名字比誤導名稱更好。【如果你懂荷蘭語,其實V和P也並非毫無意義。】

我認為其他幾對名稱會造成誤導,因為increment(遞增)和decrement(遞減)忽略了會導致阻塞和喚醒的可能性,並且訊號量通常以與signal(訊號)和wait(等待)無關的方式使用。

如果要堅持有意義的名字,那麼我會建議:

我不認為這兩個名字會很快被大家所接受。 在此期間,我選擇(或多或少有點任意地選擇)signal(訊號)和wait(等待)。

2.3 為什麼是訊號量

看一下訊號量的定義,並不容易看出它們這麼有用的原因。 確實,我們不需要訊號量來解決同步問題,但使用它們有一些優勢:

  • 訊號量強制實施有意識的約束,幫助程式設計師避免錯誤。
  • 使用訊號量的解決方案通常是乾淨且有條理的,因此很容易證明其正確性。
  • 訊號量可以在許多系統上高效實現,因此使用訊號量的解決方案是可移植的,通常是高效的。