码迷,mamicode.com
首页 > 编程语言 > 详细

Java volatile 关键字 理解

时间:2019-10-07 23:18:55      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:自增   多核   操作   lock   内存模型   过程   可见   无效   原子操作   

Java   volatile 理解  

Volatile  

1 如果一个字段被申明为volatile,那么Java内存模型则可以保证多个线程所看到的值是一致的

2  禁止指定重排。

3  volatile只能保证可见性,不能保证原子性

可见性实现原理:

 

volatile能够保证可见性,那么它是如何实现可见性的呢?以X86处理器为例,在对volatile修饰的变量进行写操作时,通过编译器生成反汇编指令后,会发现会多一条Lock前缀,就是由于这条Lock前缀所实现的可见性。Lock前缀在多核处理器中会引发下面这两件事情:

 

    Lock指令会将当前处理器缓存行的数据写回到主内存。(ps:每个处理器都有自己的cache缓存,每次缓存中操作的变量都是主内存中变量的拷贝)

    一个处理器写回主内存的操作会造成其他处理的缓存无效。

举个栗子

 

一个变量i被volatile修饰,两个线程想对这个变量修改,都对其进行自增操作也就是i++,i++的过程可以分为三步,首先获取i的值,其次对i的值进行加1,最后将得到的新值写会到缓存中。

线程A首先得到了i的初始值100,但是还没来得及修改,就阻塞了,这时线程B开始了,它也得到了i的值,由于i的值未被修改,即使是被volatile修饰,主存的变量还没变化,那么线程B得到的值也是100,之后对其进行加1操作,得到101后,将新值写入到缓存中,再刷入主存中。根据可见性的原则,这个主存的值可以被其他线程可见。

问题来了,线程A已经读取到了i的值为100,也就是说读取的这个原子操作已经结束了,所以这个可见性来的有点晚,线程A阻塞结束后,继续将100这个值加1,得到101,再将值写到缓存,最后刷入主存,所以即便是volatile具有可见性,也不能保证对它修饰的变量具有原子性。

Java volatile 关键字 理解

标签:自增   多核   操作   lock   内存模型   过程   可见   无效   原子操作   

原文地址:https://www.cnblogs.com/yxlawyer/p/11632764.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!