2012-05-24 74 views
5

我跑進一些(生產!)的代碼看起來像下面的代碼片段:分配基於該對象的synchronized塊中的對象(JAVA)

synchronized(some_object) { 
    some_object = new some_object() 
} 

我希望這是受到各種可怕的競態條件,並且第二個線程可能會輸入這個塊來創建新的對象。我的Java版本不夠好,無法明確說明上面的預期行爲,所以很好奇你們在重構這個之前不得不說的話。

回答

2

弗朗西斯說,這可能不是一個問題。您的片段等同於:

SomeObject saved = some_object; 
synchronized(saved) { 
    some_object = new SomeObject() 
} 
+0

它不是那樣寫的。在我的情況下,類有用於同步塊的變量some​​_object,並且該變量在同一塊內被重新分配。 –

+0

+1此處的關鍵是同步指的是對象,而不是參考。執行並分配'new'後,您仍然鎖定在舊對象上。此時新對象不鎖定。當同步塊退出時,舊對象的鎖定被釋放,並且如果沒有其他對它的引用,則它有資格使用gc。如果在實際的同步塊中有更多的代碼,並且它依賴鎖以某種方式轉移到新對象,那麼你可能會遇到問題。 –

+1

謝謝吉姆。鎖在物體上而不是參考對我來說是有意義的。我很模糊的是,當變量引用的對象改變時,另一個線程是否會看到一個不同的解鎖對象並再次進入該塊,或者執行同步塊的機制阻止該事件發生? –

4

這實際上可以確定取決於發生了什麼。您需要了解更大的上下文。同步將位於塊開始處some_object指向的對象上。您的描述中沒有足夠的信息來查看這是一個錯誤。

同步本身將工作得很好。

1

同步在進入同步塊時被引用的對象上。指向同步塊內另一個對象的引用根本不影響同步。它仍然在「舊」對象上同步。

1

這是非常糟糕的。同步最適用於最終班級成員。

現代的方法來創建一個線程安全的方式將對象在循環中使用的AtomicReference compareAndSet在行動(第15章)在戈茨的Java併發討論。這不會阻塞你的線程,並且提供比同步塊更高的性能。

private final AtomicReference<SomeObject> someObject = new AtomicReference<>(); 


void buildIt() { 
    SomeObject obj = new SomeObject(); 
    SomeObject current = someObject.get(); //probably null, but doesn't matter 
    while (true) { 
     if (someObject.compareAndSet(current, obj)) 
      break; 
    } 
}