栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中的volatile关键词(可见性、禁止指令重排、单例模式)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中的volatile关键词(可见性、禁止指令重排、单例模式)

目录

一、volatile变量的特性

1、保证可见性,不保证原子性

可见性?

不保证原子性?

2、禁止指令重排

二、单例模式(双重检查锁)


一、volatile变量的特性

参考:

volatile为什么不能保证原子性?_Ludwig__的博客-CSDN博客_volatile为什么不能保证原子性https://blog.csdn.net/qq_46190347/article/details/109908724Java volatile关键字最全总结:原理剖析与实例讲解(简单易懂)_老鼠只爱大米的博客-CSDN博客_java volatilehttps://blog.csdn.net/u012723673/article/details/80682208

1、保证可见性,不保证原子性

可见性?

(1)读volatile:每当子线程某一语句要用到volatile变量时,都会从主线程重新拷贝一份,这样就保证子线程的会跟主线程的一致。
(2)写volatile: 每当子线程某一语句要写volatile变量时,都会在读完后同步到主线程去,这样就保证主线程的变量及时更新。

不保证原子性?

仅在单次读或者单次写这样的原子操作中,volatile能够实现线程安全。如果遇到 i++ 这种复合操作时(i++ 复合了读取、加、赋值3步),不能保证原子性。

2、禁止指令重排

(1)当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;

(2)在进行指令优化时,不能将对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。

什么是指令重排?参考:

java排序为什么会出现多次排序结果不一样_并发理论基础:指令重排序问题_向天再借十厘米的博客-CSDN博客https://blog.csdn.net/weixin_29734285/article/details/113083692【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )_韩曙亮的博客-CSDN博客_java指令重排序https://hanshuliang.blog.csdn.net/article/details/120186485

二、单例模式(双重检查锁)

参考:

单例模式----双重检查锁_迪迪didi的博客-CSDN博客_单例模式双重校验锁https://blog.csdn.net/weixin_50005657/article/details/115803998例子:

public class TestInstance {
    private volatile TestInstance instance;

    public TestInstance getInstance() {
        //1
        if (instance == null) {
            //2
            synchronized (this) {
                //3
                if (instance == null) {
                    //4
                    instance = new TestInstance();
                }
            }
        }
        //6
        return instance;
    }
}

为什么要用同步锁synchronized就不赘述了,重点讲解为什么要用volatile?

步骤//4能被拆解成如下伪代码:

a.分配内存
memory = allocate() 

b.初始化对象
ctorInstanc(memory)

c.设置instance指向刚分配的地址
instance = memory

如果instance不被volatile修饰,伪代码中abc指令可能会被重排序。假设有两个线程A和B,线程A先执行,执行到步骤//4时,指令被重排序成acb,线程A执行完指令c后,instance已经有指向的地址,instance不再为空,但该对象还未被初始化。此时,线程B执行,在步骤//1时,判断instance不为空,直接返回一个未被初始化的对象instance。综上所述,volatile可以用来防止指令重排序。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/885141.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号