2011-02-22 29 views

回答

14

「更好」取決於上下文。根據詹姆斯麥克帕蘭的說法,他們「同樣強大」。我強烈建議觀看his blog for a discussion on the differences

這裏是一個快速指南,我發現:

信號燈

  • 可以在程序中任何地方使用,但不應該在一個顯示器中使用
  • Wait()並不總是阻止調用者(即,當信號量計數器大於零時)。
  • Signal()要麼釋放阻塞的線程(如果有的話),要麼增加信號量計數器。
  • 如果Signal()釋放阻塞的線程,則調用者和釋放的線程都會繼續。

條件變量

  • 只能在監視器
  • Wait()始終阻塞調用者使用。
  • Signal()要麼釋放阻塞的線程,如果有的話,或者信號丟失,就好像它從不發生。
  • 如果Signal()釋放阻塞的線程,調用者生成監視器(Hoare類型)或繼續(Mesa類型)。只有一個調用者或已發佈的線程可以繼續,但不能同時有兩個。

從這個信息:http://www.cs.mtu.edu/~shene/NSF-3/e-Book/MONITOR/sema-vs-monitor.html

一些有用的資源:

+3

這一般很有趣,但不直接適用於Java,因此稍有混淆。霍爾和梅薩監視器? – Air 2012-05-08 15:55:59

+0

是的,問題是針對Java問的,但答案與Java無關。 – t0r0X 2012-11-21 18:10:24

1

首先,你甲肝e決定使用哪個JDK。 僅提供線程的第一個Java版本。自Java Tiger(5.0)以來,引入了新類來處理併發。 特別提供了一個完整的包,其中包括java.util.concurrent

根據我的經驗,我發現顯示器更好,因爲它們讓代碼更乾淨。而且,使用它們讓代碼更易於理解。他們通過實現接口的類通常實現的:由JDK提供的最有名的實現是的ReentrantLock類,它定義了一個普通的鎖,以及特定的ReentrantReadWriteLock類,它提供寫和/或讀取鎖定。

因此,使用鎖來啓用/禁用對共享對象(例如對象列表)的訪問。

旗語對象是同步的用於協調和控制線(有在最新的JDK提供,如旗語的CyclicBarrierCountdownLatch,和類許多同步器)。例如,使用Semaphore,您可以將固定數量的標記釋放到您的線程池中,並決定可以同時執行的操作數量。就我個人而言,我不喜歡這種方法,因爲與Futures and Locks一起使用線程池可以以更清潔和更安全的方式獲得相同的結果。

在本書中可以找到更多信息:「Java Concurrency in Practice」,在本IBM教程中:「Concurrency in JDK 5.0」。一些更好的例子可以找到here

3

確認,通過顯示器我們的意思是舊的​​關鍵字。

第一個問題,你需要你的鎖有櫃檯嗎?

  1. 信號量可以有一個計數器大於一個。如果你需要保護N資源,信號量是最好的。輕鬆的決定。
  2. 如果您正在保護單個資源,這是信號量(1)和監視器同等適用的有趣情況。

J2SE 5.0 concurrency article在此給出了很好的建議。顯示器是有限的,因爲:

  • 沒有辦法從企圖後退,以獲取已持有的鎖,或等待一段指定的時間後放棄或取消後鎖定嘗試一箇中斷。
  • 沒有辦法改變鎖的語義,例如,在重入,讀寫保護或公平性方面。
  • 同步在方法和塊中完成,因此限制使用嚴格的塊結構鎖定。換句話說,你不能在一種方法中獲得鎖,並在另一個方法中釋放它。

因此,如果這些項目中的任何一項對您很重要 - 在超時後退出是一個很好的例子 - 那麼請使用Semaphore。如果沒有,顯示器是好的。

7

如果你有頭痛極小化後,更喜歡信號燈監視器(​​塊/方法),無論你覺得鎖定原語的真正的選擇。 忽略關於信號量靈活性的學術討論。你是在可靠性之後,而不是可配置性,不是嗎?

人們經常聲稱監視器和信號燈是等價的(可以互相模擬),但是這種等價性比sometimes expected更加抽象和有用。 任何人誰可以正確模擬一個與另一個不需要任何回答這個問題了。

很明顯,在允許同時進入塊的線程數大於1的情況下,信號量是唯一的實際選擇。因此,顯示器的真正競爭對手是二進制信號量,即那些初始化爲1的計數器,並且還包括那些您期望執行鎖定以最終解鎖信號量的線程的計算器。所以讓我們仔細看看這些情況。

監視器和二進制信號量之間的根本區別是線程所有權。它具有很大的後果,那就是重入的能力。重入意味着已經擁有鎖的線程可以重新獲取它,而不是死鎖。如果你的班級共享了你只是想用所有方法保護的狀態,但卻無法對這些方法如何相互呼叫提供永久的假設,這是一件大事。或者隨着你的線程安全計劃中發展的任何皮帶和支架特徵。

信號量永遠不會重入,Java監視器總是可重入的。即使在單線程場景中,如果您需要鎖定多個代碼位置中的同一對象semaphores are prone to deadlocks,並且信號量的侷限性只會在相對罕見的情況下帶來任何好處,無論如何監視器並不是真正的選項。

線程所有權還大大降低了忘記鎖定,忘記解鎖或一個線程的活動掩蓋另一個線程的活動的風險。在關聯的Java語法中也存在顯着的人機工程學差異。

另請注意this question;雖然它使用了不同的術語,但更好的答案在這裏理解爲「互斥體」,意味着Java「監視器」。