比方說,我有以下的,是String get/set線程安全嗎?
public class Foo{
private String bar;
public String getBar(){
return bar;
}
public void setBar(String bar){
this.bar = bar;
}
}
由於String
類的不可變的性質是這些方法會自動線程安全的,或者需要某種鎖定機制?
比方說,我有以下的,是String get/set線程安全嗎?
public class Foo{
private String bar;
public String getBar(){
return bar;
}
public void setBar(String bar){
this.bar = bar;
}
}
由於String
類的不可變的性質是這些方法會自動線程安全的,或者需要某種鎖定機制?
不,這不是線程安全的。 Foo
是可變的,所以如果你想確保不同的線程看到的bar
相同的值 - 即,一致性 - 無論是:
bar
volatile
,或AtomicReference<String>
。bar
的讀取和寫入本身是原子的,但原子性不是線程安全的。
http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
爲深入Java併發的覆蓋面,搶Java Concurrency in Practice (aka JCIP)副本。
+1或簡單地聲明'bar'爲'final',所以引用不能被重新賦值給另一個值。當然,那裏不會有任何制定者:) – 2013-02-25 17:25:25
這是不可改變的。在這種情況下不需要二傳手。而且你必須確保提供一個構造函數來初始化該值,因爲在這種情況下,一旦你退出構造函數就無法更改它。 – duffymo 2013-02-25 17:41:42
...出於好奇,做這兩件事實際上很重要嗎?我的意思是,如果你的實際問題是一種競爭條件,儘管有'易失性'或'同步',它仍然會發生 - 它只是減少它可能發生的'窗口',對吧?或者我在這裏錯過了什麼? – 2013-02-25 18:09:57
不,不安全。
這是Foo可變行爲; String的不可變性不會累積到Foo。
public class Foo{
private String bar;
public synchronized String getBar(){
return bar;
}
public synchronized void setBar(String bar){
this.bar = bar;
}
}
+1同步getBar()'怎麼辦?也許某個線程爲'bar'設置一個新值,而其他線程讀取'bar'。 – 2013-02-25 17:30:26
對不起,你對我沒有意義。我認爲你的意見只是混淆了這個問題。 – duffymo 2013-02-25 17:46:33
@duffymo做了一個非同步的getter和線程間同步setter保證一致性? – 2013-02-25 17:50:26
您正在設置參考,因此String
的不變性不起作用。您不會影響String
的內容。
不,它不是線程安全的。
雖然String
是不可變的,但問題來自Foo
的字段。爲了使這一點更加明顯,例如考慮一種方法,其作業將是附加(而不是替換)bar
的值。當它從多個線程中調用時,一些寫入可能會丟失。即使在這種情況下最初並不明顯,也可能發生同樣的(丟失的寫入)。
我假設你是指'setter中的'String'。 – 2013-02-25 17:18:54
@TheodorosChatzigiannakis,是的,我的錯!固定。 – mre 2013-02-25 17:19:10
相關的c#問題:http://stackoverflow.com/questions/3595114/why-are-immutable-objects-thread-safe – PermGenError 2013-02-25 17:20:03