Volatile关键字

一、作用

        volatile关键字的作用有3个,可见性,有序性对64位的long和double变量的读写保证原子性。

二、作用分析

可见性:多个线程访问同一个共享变量,一个线程修改了共享变量的值,其他线程能够立即可见修改后的值。

有序性:禁止指令的重排序。 CPU对一些原子性操作可能会打乱执行顺序,因为CPU执行每一条指令效率不同,为了优化而打乱原子性的顺序,但是在单线程下结果不会发生变化。

对64位的long和double保证读写的原子性:对于非volatile的64位的long和double类型, JVM允许将64位的读或写操作分为两个32位的操作,如果在多线程情况下,就可能会发生只赋值半个的情况。用volatile进行修饰的话,就能保证64位的读写操作是原子性的。

三、使用场景

1、需要保证多线程中共享变量的可见性时。

2、作为状态标识(多线程中一个线程修改,其他线程读取的情况)

3、懒汉式单例模式double-check单例模式

四、懒汉式单例模式分析

        在懒汉式单例模式中:

publice class Singleton{

private static volatile Singleton singleton;

publice statice Singleton getInstance(){

if(singleton == null){

    synchronized (singleton.class){

            if(singleton == null){

                singleton = new Singleton;

            }

        }

    }

}//为什么加volatile和synchronzied?

        在懒汉式单例模式中,volatile关键字保证了可见性和禁止指令重排序,加synchronized是因为singleton=new Sinleton不是一个原子性的操作。分为3个阶段,1.在堆内存中申请空间  2.初始化内存空间  3.把内存空间地址赋值给singleton这个变量。  在多线程的情况下,如果线程A只执行12步骤,线程B就进来了,那么B就会执行123步骤,因为singleton还没有被赋值,这种情况singleton可能会初始化两次(B执行完又切换回A了)所以需要加synchronized保证这3个操作是原子性的。   而且如果不加volatile,执行的顺序可能位132.在执行13后切换,这块内存还没有被初始化就被引用了,其他线程使用这个变量的时候则会报错。

五、内存屏障实现原理(线程通信)

volatile如何实现的这3个功能?

    通过内存屏障,说内存屏障之前先说一下多线程之间的通信。   在JMM中两个线程要实现通信必须要经过主内存,每一个线程都有一个线程私有的工作内存,主内存是共享的,通信的过程就是先修改自己的工作内存的值,然后写入到主内存中,然后其他线程读取主内存中的值完成通信。而内存屏障的实现原理就是被修饰的变量禁止指令重排序。对于线程中的写操作,写入的数据会强制刷新到主内存中,而读数据会强制从主内存中读取,使工作内存中的变量无效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

失忆机器

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

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

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

打赏作者

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

抵扣说明:

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

余额充值