[英]Volatile class instances and member access in Java
我认为我在做的事是正确的,但是既然这样可能会很严重地爆发,所以我很想澄清一下。
该代码是尝试说明问题的示例,对于任何轻微的错字,我们深表歉意。
我有以下课程
public class Components
{
public final String mVar1;
public final boolean mVar2;
public Components(String var1, boolean var2)
{
mVar1 = mVar1;
mVar2 = mVar2;
}
}
如果我创建此类的易失性实例,我相信将该组件的值分配给已创建的组件的地址并在内存中是线程安全的。
public class Storage
{
public static volatile Components sComponents = null;
}
因此,无论我是在主线程上还是在其他线程上设置此变量(一个集合将其简单地指向已创建的对象,而不创建一个新对象),它都应该是线程安全的,因为volatile关键字作用于组件引用,该引用将被更新以指向已经存在的对象。
因此,例如
public class ThreadedClass
{
public ThreadedClass()
{
// Create an instance of Components so we have something to copy
mInitialComponents = new Components("My String", false);
// Spin off a thread
create_a_new_thread( threadEntryPoint );
}
// This function is called every frame on the main thread
public void update()
{
// If we have our components, print them out
if (Storage.sComponents != null)
{
print(sComponents.mVar1);
print(sComponents.mVar2);
}
}
private Components mInitialComponents = null;
private void threadEntryPoint()
{
// Just sleep for a bit so update gets called a few times
sleep(3000);
// Set our components
Storage.sComponents = mInitialComponents;
}
}
(在现实世界的代码中,mInitialComponents是通过同步函数创建和访问的,因此访问原始对象是线程安全的)。
因此,我的问题是,在主线程或任何其他线程上调用update时,一旦将Storage.sComponents设置为threadEntryPoint中的现有对象,它是否只是更新对象引用,因此只要我们将对象保证是完整的,检查是否为空。
或者是否可能已正确分配了一些内部成员或没有内部成员。
谢谢
您的update方法不是线程安全的,并且可能引发null指针异常。 可以通过将其更改为:
// This function is called every frame on the main thread
public void update()
{
final Components components = Storage.sComponents;
// If we have our components, print them out
if (components != null)
{
print(components.mVar1);
print(components.mVar2);
}
}
组件中的内部值是最终版本,可以安全使用。 这是假定您不会从其构造函数中泄漏对Components实例的引用。
可以肯定地假设,如果components
不为null,则其成员变量已正确初始化。 根据Java虚拟机规范,通过对从new
返回的对象的引用进行的任何访问都可以保证看到该对象中所有final
字段的完全初始化版本。 请参阅JVM规范,第17.5章。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.