比方说,我有以下的,是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