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?spm=1001.2014.3001.5506

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?spm=1001.2014.3001.5506【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )_韩曙亮的博客-CSDN博客_java指令重排序https://hanshuliang.blog.csdn.net/article/details/120186485?spm=1001.2014.3001.5506

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

参考:

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

(这属于懒汉模式,初次使用时才实例化。【饿汉模式:一开始就实例化】)

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可以用来防止指令重排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码与咖啡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值