要清楚:我主要是嵌入的東西,即它是C和微控制器中的某種實時內核;但實際上這個問題應該是平臺無關的。 Mutexes and Semaphores Demystified,以及本related answer on StackOverflow:計數信號量的使用案例
我由邁克爾·巴爾讀好文章。我清楚地明白什麼是二進制信號量,什麼是互斥量。那很棒。
但說實話,我從來不知道,還是不能懂,還有什麼所謂的計數信號量(即,最大信號計數> 1)可以。我應該在什麼情況下使用它?很久以前,在我讀過邁克爾巴爾的前述文章之前,我已經告訴過類似於「」的東西,你可以在有的時候使用它,比如有一定數量的牀的旅館房間。是信號量的最大計數,就像該房間的一些鍵號「。
這可能聽起來好聽,但實際上我從來沒有在我的編程實踐中有過這樣的情況(和無法想象任何)和邁克爾·巴爾說,這種做法是錯誤的,他似乎是正確的。
然後,我讀過的文章後,我認爲當我有,說出來可能會被使用,某種FIFO緩存。假設緩衝區的容量是10個元素,我們有兩個任務:A(生產者)和B(消費者)。然後:
- 信號量的最大數應該設置爲10;
- 當A希望將數據放入緩衝區,它
signal
S中的信號。 - 當B想要從緩衝區獲取數據時,它是
wait
的信號量。
好,但它不工作:
- 如果A試圖把新的數據到FIFO,但沒有房呢?它如何等待這個地方:它應該在撥出新數據之前撥打
signal
(並且signal
然後應該能夠等到最大計數爲<最大計數)?如果是這樣,信號量將在數據實際存入FIFO之前發出,這是錯誤的。 - 信號量不足以實現正確的同步:FIFO本身也需要同步。然後,它產生了經典的TOCTTOU問題:有一段時間信號量已經被髮送或等待,但是FIFO尚未被修改。
那麼,我應該什麼時候使用那個野獸,計數信號量呢?
好吧,從生產者P1完成等待「可用」並鎖定互斥鎖的那一刻起,所以,可能有其他生產者P2中斷了這個序列(並首先鎖定了互斥體)。然後,P1鎖定互斥鎖,但隊列已滿,P1必須解鎖互斥鎖並再次等待「可用」。這真的很好嗎?哇,只有一個數據隊列的三個對象。我使用的實時內核(TNeoKernel:https://bitbucket.org/dfrank/tneokernel)提供了提供原子等待和放置數據以及原子等待和獲取數據操作的數據隊列。 – 2014-10-07 08:56:52
好吧,從生產者P1完成等待「可用」並鎖定互斥鎖的那一刻起,因此,在這種情況下,可能有其他生產者P2中斷了該序列(並且先鎖定互斥體)',因爲這兩個線程都從'可用'信號量獲得了單元,所以在該隊列中必須有兩個空閒空間,所以兩者線程可以推送他們的對象而不會溢出隊列。您建議的實時內核 - 它允許與任意數量的生產者/消費者進行阻塞,有界的隊列? – 2014-10-08 02:32:37
此外,你可以用'無鎖'隊列替換'簡單隊列和互斥'。只要無鎖隊列類對於多個生產者和消費者是無條件安全的。 – 2014-10-08 02:37:43