volatile

一个被volatile修饰的共享变量具备两层语义:
1、保证可见性,即某线程修改了该变量的值,则新值对其他线程来说是立即可见的。不保证原子性。
正常情况下:为了提高处理速度,每个线程都有自己的缓存,同时在各自缓存中都有一份共享变量的副本,各线程对共享变量的修改也仅仅是针对自身缓存的副本。那么当某线程对共享变量进行更改时,其他线程并不知情。

当使用volatile修饰:

  • 修改后的变量值会被立即写入主存。
  • 某个线程对共享变量进行的更改,会导致其他线程缓存中的该共享变量无效。当其他线程再次读取共享变量时发现自己的缓存行无效,则会重新把数据从主存加载到缓存。

之所以说不保证原子性:
如i++,它包括3个原子操作:读取变量的原始值、进行加1操作、写入缓存。若多个线程在执行第一个原子操作后被阻塞,则当某个线程执行i++后,这些线程并不知情,从而导致i只加1。

2、禁止进行指令重排序。
正常情况下,为了在不改变单线程下程序执行结果的前提下,优化程序的运行效率,编译器或CPU会自动对指令进行优化,从而导致各指令之间执行的先后顺序发生变化。
volatile禁止指令重排序有两层意思:

volatile禁止指令重排序有两层意思:

  • 在进行指令优化时,不能将“对volatile变量访问的语句”调整到该语句前面的命令之前,也不能把“对volatile变量访问的语句”调整到该语句后面的命令之后。
  • 当程序执行到volatile变量的读/写操作时,其前面的操作肯定都已经完成(前面指令的先后顺序不保证)且执行结果对后面的操作可见,而在其后面的操作肯定还没有进行。

如单例模式:

class Singleton
{
    private volatile static Singleton instance = null;
    private Singleton() {}

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

其中语句“instance = new Singleton()”并非是一个原子操作,它包括3个操作:
(1)给instance分配内存
(2)调用Singleton的构造函数来初始化成员变量
(3)将instance对象指向分配的内存空间。

指令重排时,2和3的执行顺序是不能保证的(1-2-3或 1-3-2)。若为后者,则当某线程在3执行完毕、2未执行之前被其他线程抢占,则其他线程会返回一个未初始化的instance。

volatile实现原理

1、可见性。

  • 当对volatile变量进行写操作时,编译器会向处理器发送一条Lock前缀的指令。该命令会强制修改后的值写回到主存,从而确保了若某线程对volatile变量进行修改,则会立即更新主存中数据。
  • 在多处理器环境下,各处理器会检查自己的缓存是否过期。当处理器发现自己缓存行对应的内存地址被修改了,就会将该缓存行设置成无效状态;当处理器要对该volatile变量进行读写操作时,会强制重新把数据从系统内存加载到处理器缓存中,从而确保了其他线程获取的volatile变量都是从主存中获取最新的。

2、有序性。

  • Lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值