【发布时间】:2014-08-09 23:19:21
【问题描述】:
好吧,考虑下面给出的不可变类Immutable:
public final class Immutable
{
final int x;
final int y;
public Immutable(int x,int y)
{
this.x = x;
this.y = y;
}
//Setters
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
}
现在我在 Sharable 类中创建一个 Immutable 对象,该对象将由多个线程共享:
public class Sharable
{
private static Immutable obj;
public static Immutable getImmutableObject()
{
if (obj == null) --->(1)
{
synchronized(this)
{
if(obj == null)
{
obj = new Immutable(20,30); ---> (2)
}
}
}
return obj; ---> (3)
}
}
Thread A 将obj 视为null 并移动到同步块并创建对象。现在,由于 Java 内存模型 (JMM) 允许多个线程在对象初始化开始之后但结束之前观察对象。 因此,Thread B 可以看到对obj 的写入正在发生在写入Immutable 的字段之前。因此,Thread B 可以看到部分构造的 Immutable,它很可能处于无效状态,并且其状态可能会在以后意外更改。
这不是让Immutable 成为非线程安全的吗?
编辑
好的,在对 SO 进行了大量查找并彻底了解了一些 cmets 之后,我知道 您可以在线程之间安全地共享对不可变对象的引用 在构造对象后。此外,正如@Makoto 所提到的,通常需要将包含其引用的字段声明为 volatile 以确保可见性。此外,正如@PeterLawrey 所述,将对不可变对象的引用声明为final 使该字段为thread-safe
【问题讨论】:
-
你可以写
public class Sharable { public static final Immutable obj = new Immutable(); }这样会更简单,线程安全。
标签: java multithreading thread-safety immutability