2013-03-28 17 views
4

如果你有一次只有一次人應該訪問的資源,你可以使用大小爲1的信號量,或者你可以只使用一個ReentrantLock實例?規模1的信號量是最好的選擇?

使一個或另一個更好的決定的微妙差異是什麼?

+2

爲什麼不'synchronized'? – NPE 2013-03-28 10:16:11

+2

我不認爲會有任何 - 當'permit'設置爲1時,2個API變得幾乎相同。並且這兩個實現都基於'AbstractQueuedSynchronizer',所以行爲和性能應該接近相同。 – assylias 2013-03-28 10:16:13

回答

5

有差異:

  1. 信號燈可以由一個線程來獲取和另一個線程釋放。這樣,一個線程可以發信號通知另一個線程。計數爲1的信號也可用於互斥。另一方面,鎖只用於相互排斥。
  2. 信號量不可重入。這意味着當許可證耗盡時,即使線程已被同一線程獲取,線程也無法獲取信號量。鎖可以是可重入的。
1

Semaphore s很適合計數許可/發佈,所以如果你有多個資源,Lock等。對你無能爲力。但是如果你只有一種資源需要防範,那麼它們已經足夠好了。

+0

@Raif H絕對零差呢?只有我能想到的是,如果你不是100%確定它總是限制爲1。 – 2013-03-28 10:18:08

+0

就像assylias所說的那樣,它們(和'java.util.concurrent'中的許多其他)基於'AbstractQueuedSynchronizer',並將具有相同的性能特徵。爲你選擇正確的語義。 – 2013-03-28 10:28:46

0

計數信號量示例:您有一個受保護的對象,並允許同時訪問不超過五個線程的限制。在這種情況下,初始值爲5的計數信號量就是數學擬合。 Downey's Little book of Semaphores是理解構造的最佳讀物之一。

+1

雖然屬實,但我不明白這是如何回答這個問題的。 – NPE 2013-03-28 10:24:05

0

雖然這是事實,這可能與兩個​​完成,並且Semaphore你首先必須弄清楚你將如何使用這些資源。如果您使用​​這意味着你將不得不在同步觀看主題:

public void run() { 
    // some code 
    synchronized (resource) { 
    // use resource 
    } 
} 

如果你不想讓線程觀看的(這在我看來是更好),在getter方法使用Semaphore資源:

public Resource acquireResource() { 
    // acquire semaphore 
    return resource; 
} 

public void releaseResource() { 
    // release semaphore 
} 

和線程只是做:

public void run() { 
    // some code 
    Resource resource = ResourceContainer.getResource(); 
    // do something with resource 
    releaseResource(); 
} 

您可以Object參數添加到這些方法只是比較如果同一個對象釋放信號量。