当前位置:  开发笔记 > 编程语言 > 正文

是否建议始终对同步块/方法使用volatile变量?

如何解决《是否建议始终对同步块/方法使用volatile变量?》经验,为你挑选了1个好方法。

据我所知,volatile有助于内存可见性并synchronized有助于实现执行控制.Volatile只是保证线程读取的值将写入最新值.

考虑以下:

public class Singleton{
    private static volatile Singleton INSTANCE = null;

    private Singleton(){}

    public static Singleton getInstance(){
        if(INSTANCE==null){
             synchronized(Integer.class){
                 if(INSTANCE==null){
                     INSTANCE = new Singleton();
                 }
             }
        }
        return INSTANCE;
    }
}

在上面的代码中,我们使用双重检查锁定.这有助于我们只创建一个Singleton实例,这是communicated通过创建线程尽快创建的其他线程.这就是关键字的volatile作用.我们需要上面的内容,synchronized block因为线程读取INSTANCE变量的延迟为null并初始化对象可能会导致a race condition.

现在考虑以下内容:

public class Singleton{
    private static Singleton INSTANCE = null;

    private Singleton(){}

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

假设我们有2个线程t1t2试图获取该Singleton对象.线程首先t1进入getInstance()方法并创建INSTANCE对象.现在,这个新创建的对象应该对所有其他线程可见.如果INSTANCE变量不是volatile那么我们如何确保对象仍然不在t1's内存中并且对其他线程可见.如何尽快在上述INSTANCE被初始化t1可见的其他线程?

这是否意味着始终使变量易变为同步?在什么情况下我们不要求变量是易变的?

PS我已经在StackOverflow上阅读了其他问题,但找不到我的问题的答案.请在投票前发表评论.

我的问题来自这里给出的解释



1> Jon Skeet..:

我认为你所缺少的是JLS 17.4.4:

监视器m上的解锁动作与m上的所有后续锁定动作同步(其中"后续"根据同步顺序定义).

这与关于volatile变量的内容非常相似:

对易失性变量v(第8.3.1.4节)的写入与任何线程对v的所有后续读取同步(其中"后续"根据同步顺序定义).

然后在17.4.5:

如果动作x与后续动作y同步,那么我们也有hb(x,y).

......其中hb是"发生在之前"的关系.

然后:

如果一个动作发生在另一个动作之前,则第一个动作在第二个动作之前可见并在第二个之前被命

内存模型非常复杂,我并不认为自己是专家,但我的理解是引用部分的含义是你所展示的第二种模式是安全的,而变量不是易变的 - 实际上任何变量都是是修改和同步块内的读出对于相同的显示器是不是挥发性安全.对我来说,更有趣的方面是变量值引用的对象内的变量会发生什么.如果Singleton不是不可变的,你仍然可能在那里遇到问题 - 但这一步就被删除了.

更具体地说,如果两个线程调用getInstance()INSTANCE为null,则其中一个线程将首先锁定监视器.INSTANCE在解锁操作之前发生非空引用的写操作,并且在另一个线程的锁定操作之前发生解锁操作.锁定操作发生在读取INSTANCE变量之前,因此写入发生在读取之前...此时,我们保证写入对读取线程可见.

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有