2011-04-08 47 views
10

什麼時候會使用信號量?什麼時候應該使用信號量?

唯一的例子我能想到的是限制同時訪問相同的數據/代碼的線程數...

任何其他場景中,信號量將是最好的解決辦法?

+2

相關:http://stackoverflow.com/questions/2350544/in-what-situation-do-you-use-a-semaphore-over-a-mutex-in-c – 2011-04-08 20:20:02

+0

舉一個例子:http://堆棧溢出。/ 2375132/releasesemaphore-does-not-release-the-semaphore/2375370#2375370 – 2011-04-08 20:49:24

回答

5

信號量可能適合進程之間的信號傳遞。 對於多線程編程,應該避免使用信號量。如果您需要獨佔訪問資源,請使用互斥鎖。如果您需要等待信號,請使用條件變量。

即使是最經常提到的資源池的情況,與條件變量相比,使用條件變量可以更簡單,更安全。我們來看看這種情況。一個天真的實現與信號會是什麼樣子(僞):

wait for semaphore to open 
take a resource out of the pool 
use the resource 
put it back to the pool 
open the semaphore for one more thread 

的第一個問題是信號不保護池從多個線程訪問。所以,需要另一種保護。讓它成爲一個鎖:

wait for semaphore to open 
acquire the lock for the pool 
take a resource out of the pool 
release the lock 
use the resource 
acquire the lock 
put the resource back to the pool 
release the lock 
open the semaphore for one more thread 

需要採取額外的措施,以確保池訪問時不是空的。從技術上講,可以繞過信號量來訪問池,但它會破壞上述獲取過程的資源可用性保證。所以池應該只能通過該過程訪問。

到目前爲止好,但如果一個線程不想被動等待資源呢?是否支持無阻塞資源獲取?如果信號量本身支持非阻塞採集,這很容易;否則(例如在Windows上),這將是有問題的。信號量不能被繞過,因爲它會打破阻塞情況。只有在池不空的情況下才能通過信號量,如果在鎖下完成,可能會導致死鎖,但一旦釋放鎖,檢查空閒的結果將變得毫無用處。這可能是可行的(我沒有嘗試),但肯定會導致顯着的額外複雜性。

使用條件變量,可以很容易地解決這個問題。下面是阻止收購的僞代碼:

acquire the lock 
while the resource pool is empty, 
    wait for condition variable to be signaled 
take a resource out of the pool 
release the lock 
use the resource 
acquire the lock 
put the resource back to the pool 
release the lock 
signal the condition variable 

在這種情況下是沒有問題的補充無阻塞收購:

acquire the lock 
if the resource pool is not empty, 
    take a resource out of the pool 
release the lock 
if the pool was empty, return 

正如你可以看到,它甚至不需要訪問條件變量,並且不會對阻塞情況造成傷害。對我來說,它明顯優於使用信號量。

3

連接池。

I.e.你有20個連接和150個線程。在這種情況下,您將擁有一個信號量來控制對20個連接的訪問​​。

+0

+1:一個很好的簡單例子,但我想知道是否還有其他情況下信號量對於... – 2011-04-08 20:25:29

2

信號量可以通過一個線程獲取並在另一個線程中釋放。鎖通常不能這樣做。當線程A完成使用資源並將資源的控制權傳遞給線程B時,我已經使用了這個。我必須控制順序以避免在這種特定情況下發生死鎖。

相關問題