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

java并发中的volatile关键字(二)

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

java并发中的volatile关键字(二)

Volatile

volatile是java虚拟机提供的轻量级的同步机制。其主要有如下两个作用
1.保证被volatile修饰的共享变量对所有线程总数可见的。
2.禁止指令重排序优化
volatile禁止重排优化
首先关于指令重排前面已详细分析过了,那么volatile是如何实现指令重排优化的。
那么我们先了解一下,内存屏障(Memory Barrier)
硬件层的内存屏障
Intel硬件提供一系列的内存屏障,主要有:
1.Ifence,是一种读屏障
sfence,是一种写屏障
mfence,是一种全能型的屏障,包含ifence和sfence
lock前缀,不是一种内存屏障,但是能完成类似内存屏障的功能。会对cpu总线和高速缓存加锁(后期跟MESI协议一起讲),是cpu指令级的一种锁、
不同硬件实现内存屏蔽的方式不同,java内存模型屏蔽了这种底层硬件平台差异,jvm提供了四类内存屏障指令:loadload,storestore,loadstore,storeload
内存屏障,又称内存栅栏,是一个cpu指令,作用有两个,一是保证特定操作的执行顺序,二是某些变量的内存可见性(利用该特性实现volatile的内存可见性)。编译器和处理器都执行指令重排优化。
案例:在单例模式中的双重检测的代码,必须给声明的私有变量添加volatile,不添加会在多线程的环境下出问题的。

下面展示一些 内联代码片。

public class DoubleSinglateDemo {
    private DoubleSinglateDemo() {}
    private static DoubleSinglateDemo instance;
    // private volatile static DoubleSinglateDemo instance1;
    public static DoubleSinglateDemo getInstance() {
        if(null == instance) {
            synchronized (DoubleSinglateDemo.class) {
                if (null == instance) {
                //在多线程环境下可能出现问题,但是如果加上volatile就可以了,why?
                    instance = new DoubleSinglateDemo();
                }
            }
        }
        return instance;
    }
}

那为什么加volatile就可以解决了呢?

通过idea中的编译工具,你会看见 instance = new DoubleSinglateDemo();在编译后会分成三步
1 .memory = allocate();//1.分配对象内存空间
2.instance(memory);// 2.初始化对象
3.instance = memory //3.设置instance指向刚分配的内存地址。
由于这部分如果不加volatile关键字,会出现指令重排现象,如果2,3步颠倒了。
1 .memory = allocate();//1.分配对象内存空间
2.instance = memory //3.设置instance指向刚分配的内存地址。
3.instance(memory);// 2.初始化对象
如果一个线程a执行到第2步是,时间片用完,线程阻塞,另一个线程B再执行这段代码,其会以为对象已经创建,但是对象没有初始化,这个线程再调该对象里面的方法时会出现报错。所以可以通过volatile禁止指令重排优化。

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

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

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