是什么使单个实例挥发性同时采用双锁点? [重复](What is the point of ma

2019-06-26 12:44发布

这个问题已经在这里有一个答案:

  • 为什么在双挥发性用于检查锁定 6个回答
private volatile static Singleton uniqueInstance

在单身时使用的同步双锁方法为什么是单实例声明为volatile吗? 我可以不声明它是挥发性实现相同的功能?

Answer 1:

volatile的代码并不多线程正常工作。

维基百科的双检锁 :

由于J2SE 5.0的,这一问题已得到修复。 volatile关键字现在确保多个线程正确处理单一实例。 这个新的成语中描述的“双检锁断了”宣言 :

// Works with acquire/release semantics for volatile
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        Helper result = helper;
        if (result == null) {
            synchronized(this) {
                result = helper;
                if (result == null) {
                    helper = result = new Helper();
                }
            }
        }
        return result;
    }

    // other functions and members...
}

一般来说,你应该避免双重检查锁定如果可能的话,因为它是很难得到正确的,如果你把它错了,它可能很难找到错误。 试试这个简单的方法来代替:

如果辅助对象是静态的(每个类装载器),一种替代方案是在需要保持器成语初始化

// Correct lazy initialization in Java 
@ThreadSafe
class Foo {
    private static class HelperHolder {
       public static Helper helper = new Helper();
    }

    public static Helper getHelper() {
        return HelperHolder.helper;
    }
}


Answer 2:

volatile防止记忆被重新排序写道,使它不可能为其他线程通过单的指针读你单身的未初始化的领域。

考虑这种情况:线程A发现uniqueInstance == null ,锁具,证实它仍然null ,并要求单的构造。 该构造使得写入成员XYZ内辛格尔顿,并返回。 线程A现在写参照新创建的单进uniqueInstance ,并准备释放锁。

正如线程A已经准备好释放锁,线程B走来,并发现uniqueInstancenull 。 螺纹B访问uniqueInstance.XYZ认为它已被初始化,但因为CPU已经重新排序写道,线程A已经写入数据XYZ尚未作出可见线程B.因此,线程B看到内部的不正确的值XYZ ,这是不对的。

当您标记uniqueInstance挥发, 内存屏障插入。 那之前发起的所有写入uniqueInstance的前完成uniqueInstance被修改,从而防止上述的重新排序的情况。



Answer 3:

为了避免使用双锁,或挥发性我用的是后续

enum Singleton {
     INSTANCE;
}

创建实例很简单,懒加载和线程安全的。



Answer 4:

写volatile字段的任何读取操作之前会发生。 下面是更好地了解一个示例代码:

private static volatile ResourceService resourceInstance;
//lazy Initialiaztion
public static ResourceService getInstance () {
    if (resourceInstance == null) { // first check
        synchronized(ResourceService.class) {
            if (resourceInstance == null) { // double check
                // creating instance of ResourceService for only one time
                resourceInstance = new ResourceService ();                    
            }
        }
    }
    return resourceInstance;
}

此链接可以为您提供更好http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html



Answer 5:

您可以使用如下代码:

private static Singleton uniqueInstance;

public static synchronized Singleton getInstance(){
    if(uniqueInstance == null){
        uniqueInstance = new Singleton();
    }
    return uniqueInstance
}


文章来源: What is the point of making the singleton instance volatile while using double lock? [duplicate]