2012-07-09 321 views
0

我正在尋找關於同步塊的說明。考慮這個類 -Java - 同步對象/塊

public class A{ 
Map map; 

public getValue(String key){ 
    return map.get(key); 
} 

public remove(String key){ 
    synchronized(map){ 
    map.remove(key); 
    } 
} 
} 

A是一個單身人士。 getValue在整個應用程序中被多個線程大量訪問。我添加一個新的方法,刪除,從地圖中刪除一個鍵。如果刪除是按照上述方式執行的,那麼

  1. 當一個線程在remove方法的同步塊中時,我認爲它會獲取地圖對象上的一個鎖。這是否意味着嘗試通過getValue方法訪問地圖的其他線程將被阻止? (我希望他們)
  2. 當同步的remove方法中沒有線程時,線程將像往常一樣訪問getValue方法函數,即不會互相阻塞? (我也喜歡)。

我希望getValue線程只有在有線程執行刪除操作時纔會阻塞。

+0

只有同步的塊纔會阻塞。 – 2012-07-09 18:47:19

回答

0

synchronized的一個規則是,對於同一個foo,一次只能有一個線程在synchronized(foo)塊中。這就是只有規則​​。

嗯,有關於記憶障礙等的一些複雜的東西,和線程可以同時在幾個嵌套synchronized(foo)塊相同foo

void thing() { 
    synchronized(foo) { 
    stuff(); // this works fine! 
    } 
} 
void stuff() { 
    synchronized(foo) { 
    doMoreStuff(); 
    } 
} 

...但上述規則基本上是理解​​的關鍵。

4

當一個線程在remove方法的同步塊中時,我認爲它會獲取地圖對象上的一個鎖。這是否意味着嘗試通過getValue方法訪問地圖的其他線程將被阻止?

不是。這意味着你有問題,除非你碰巧使用線程安全的地圖實現。

當remove方法的同步塊中沒有線程時,將像往常一樣訪問getValue方法函數的線程即不相互阻塞? (我也喜歡)。

他們不會互相阻止,不會。再次,您需要確保您使用的任何Map實現都可以,儘管可能比寫作的同時讀取還好。

您應該考慮使用ConcurrentMap實現(例如ConcurrentHashMap),此時根本不需要任何同步。

如果你不能使用,我建議你在同步兩個getValueremove - 和測量性能。獲取無鎖的鎖相當便宜 - 你真的需要去鎖無? (使用ConcurrentHashMap爲避免這個問題,當然是一個相當簡單的方式,但你應該總是考慮額外的複雜性是需要啓動微優化之前,實現您所需要的性能。)

+0

感謝您的快速回答。所以,當你說同步(對象)時,是否意味着如果兩個線程到達該代碼塊,必須彼此等待以使用同步對象?那只是該方法中的線程會阻塞彼此以訪問該對象?謝謝! – septerr 2012-07-09 18:50:36

+0

@septerr:不,不僅僅是該方法中的線程 - 任何試圖在該對象監視器上同步的線程。基本上,想象每個物體都附帶一個掛鎖。沒有*自動*鎖定掛鎖,但只要一個線程可以鎖定它,無論它被要求鎖定它。 – 2012-07-09 18:53:19

+1

'synchronized'的一個規則是,對於同一個'foo',一次只能有一個線程在'synchronized(foo)'塊中。這是'synchronized'的_only_規則。 – 2012-07-09 18:53:31

1

你不顯示Map實例如何實例化,但假設它不是線程安全的集合實例,則此代碼爲而不是線程安全。

+0

這是一個普通的HashMap。感謝你的回答。我試圖在不影響性能的情況下使其線程安全。 remove方法將很少被調用,而getValue會被調用很多。我將閱讀ConcurrentMap。 – septerr 2012-07-09 18:53:50

0

1。getValue()不同步,當一個線程獲得一個對象的鎖定時,它可以控制所有同步塊...不是非同步塊。 所以其他線程可以訪問getValue()如線程處於sychronized(圖)塊

2.使用哈希表,這是一個sychronized MAP

0

您有

一個雞和蛋的問題,我想的getValue線程只有當有線程執行時才阻塞刪除操作。

沒有某種線程間交互,你不能確定是否有其他線程執行remove

實施getValue(...)的正確方法是在地圖上進行同步。

我建議您放棄自己的鎖定,並使用ConcurrentHashMap並將大量工作用於併發性能。