考虑下面的类:
public class MyClass
{
private MyObject obj;
public MyClass()
{
obj = new MyObject();
}
public void methodCalledByOtherThreads()
{
obj.doStuff();
}
}
由于 obj 是在一个线程上创建并从另一个线程访问的,因此当调用 methodCalledByOtherThread 时 obj 是否可以为 null?如果是这样,将 obj 声明为 volatile 是否是解决此问题的最佳方法?将 obj 声明为 Final 会有什么不同吗?
编辑: 为了清楚起见,我认为我的主要问题是: 其他线程是否可以看到 obj 已被某个主线程初始化,或者 obj 是否已过时(null)?
最佳答案
要使 methodCalledByOtherThreads
被另一个线程调用并导致问题,该线程必须获取对 MyClass
对象的引用,该对象的 obj
字段未初始化,即。构造函数尚未返回。
如果您从构造函数中泄漏了 this
引用,则这是可能的。例如
public MyClass()
{
SomeClass.leak(this);
obj = new MyObject();
}
如果 SomeClass.leak()
方法启动一个单独的线程,在 this
引用上调用 methodCalledByOtherThreads()
,那么您将得到问题,但无论 volatile
如何,这都是事实。
由于您没有我上面描述的内容,因此您的代码没问题。
关于已初始化对象的 Java 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20810210/