Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的易失性类实例和成员访问_Java_Multithreading_Thread Safety_Volatile - Fatal编程技术网

Java中的易失性类实例和成员访问

Java中的易失性类实例和成员访问,java,multithreading,thread-safety,volatile,Java,Multithreading,Thread Safety,Volatile,我认为我所做的是正确的,但如果不是这样的话,这可能会爆炸得非常严重,我真的希望得到澄清 这段代码是一个试图表达这一点的例子,很抱歉有任何小的打字错误 我有以下课程 public class Components { public final String mVar1; public final boolean mVar2; public Components(String var1, boolean var2) { mVar1 = mVar1;

我认为我所做的是正确的,但如果不是这样的话,这可能会爆炸得非常严重,我真的希望得到澄清

这段代码是一个试图表达这一点的例子,很抱歉有任何小的打字错误

我有以下课程

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关键字作用于Components引用,该引用将被更新为指向已存在的对象

比如说

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中的现有对象,它是否只是更新对象引用,以便在检查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实例的引用。

可以安全地假设,如果
Components
不为null,则其成员变量已正确初始化。根据Java虚拟机规范,通过引用从
new
返回的对象进行的任何访问都保证可以看到该对象中任何
final
字段的完全初始化版本。请参阅JVM规范,第章