9

假设我有以下内容,

public class Foo{
    private String bar;

    public String getBar(){
        return bar;
    }

    public void setBar(String bar){
        this.bar = bar;
    }
}

由于类的不可变特性,这些方法是自动线程安全的String,还是需要一些锁定机制?

4

4 回答 4

19

不,这不是线程安全的。Foo是可变的,所以如果你想确保不同的线程看到相同的值bar——即一致性——或者:

  • 制作bar volatile, 或
  • 制定方法synchronized,或
  • 使用AtomicReference<String>.

的读写bar本身是原子的,但原子性不是线程安全的。

http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html


如需深入了解 Java 并发,请获取Java Concurrency in Practice (aka JCIP)的副本。

于 2013-02-25T17:18:56.123 回答
7

您正在设置引用,因此String' 的不变性不会发挥作用。您不会影响String.

于 2013-02-25T17:19:30.077 回答
5

不,不安全。

这是 Foo 可变行为;String 的不变性不属于 Foo。

public class Foo{
    private String bar;

    public synchronized String getBar(){
        return bar;
    }

    public synchronized void setBar(String bar){
        this.bar = bar;
    }
}
于 2013-02-25T17:18:50.447 回答
3

不,它不是线程安全的。

虽然String是不可变的,但问题来自Foo. 为了使这一点更明显,例如考虑一个方法,其工作是附加(而不是替换) 的值bar。当从多个线程调用它时,一些写入可能会丢失。即使在这种情况下最初并不明显,您的简单设置器也可能发生相同的(丢失的写入)。

于 2013-02-25T17:23:17.737 回答