volatile关键字

volatile关键字是由JVM提供的最轻量级同步机制。保证可见性、有序性

Java内存模型:
Java内存模型由Java虚拟机规范定义,用来屏蔽各个平台的硬件差异。简单来说:所有变量储存在主内存。
每条线程拥有自己的工作内存,其中保存了主内存中线程使用到的变量的副本。
线程不能直接读写主内存中的变量,所有操作均在工作内存中完成。

对被volatile修饰的变量进行操作时,需要满足:
a:线程对变量执行的前一个动作是load时才能执行use,反之只有后一个动作是use时才能执行load。线程对变量的read,load,use动作关联,必须连续一起出现。-----这保证了线程每次使用变量时都需要从主存拿到最新的值,保证了其他线程修改的变量本线程能看到。
b:线程对变量执行的前一个动作是assign时才能执行store,反之只有后一个动作是store时才能执行assign。线程对变量的assign,store,write动作关联,必须连续一起出现。-----这保证了线程每次修改变量后都会立即同步回主内存,保证了本线程修改的变量其他线程能看到。
c:有线程T,变量V、变量W。假设动作A是T对V的use或assign动作,P是根据规则2、3与A关联的read或write动作;动作B是T对W的use或assign动作,Q是根据规则2、3与B关联的read或write动作。如果A先与B,那么P先与Q。------这保证了volatile修饰的变量不会被指令重排序优化,代码的执行顺序与程序的顺序相同。

volatile使用

  • volatile修饰变量
  • 保证可见性、有序性

volatile特征

  • 1)保存内存可见性
  • volatile修饰的变量不会缓存到工作内存中,每一次读取获取最新volatile变量
  • (所有线程的共享变量都存储在主内存中,每一个线程都有一个独有的工作内存,每个线程不直接操作在主内存中的变量,而是将主内存上变量的副本放进自己的工作内存中,只操作工作内存中的数据。当修改完毕后,再把修改后的结果放回到主内存中。每个线程都只操作自己工作内存中的变量,无法直接访问对方工作内存中的变量,线程间变量值的传递需要通过主内存来完成。)
  • 2)禁止指令重排序
  • Java内存不会对volatile指令进行重排序,从而保证对volatile的执行顺序永远是按照书写顺序执行的

原理:

volatile可以保证线程可见性且提供了一定的有序性,但是无法保证原子性。
在JVM底层volatile是采用“内存屏障”来实现的。
观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令,lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

a)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

b)它会强制将对缓存的修改操作立即写入主存;

c)如果是写操作,它会导致其他CPU中对应的缓存行无效。

volatile与synchronized的区别
(1)使用上的区别
Volatile只能修饰变量,synchronized只能修饰方法和语句块

(2)对原子性的保证
synchronized可以保证原子性,Volatile不能保证原子性

(3)对可见性的保证
都可以保证可见性,但实现原理不同

Volatile对变量加了lock,synchronized使用monitorEnter和monitorexit monitor JVM

(4)对有序性的保证
Volatile能保证有序,synchronized可以保证有序性,但是代价(重量级)并发退化到串行

(5)其他
synchronized引起阻塞
Volatile不会引起阻塞

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值