③ 当第一个操作是volatile写 。第二个操作是volatile读时 。不能重排序 。
(2) volatile的内存屏障
①volatile写
文章插图
storestore屏障:对于这样的语句store1; storestore; store2 。在store2及后续写入操作执行前 。保证store1的写入操作对其它处理器可见 。(也就是说如果出现storestore屏障 。那么store1指令一定会在store2之前执行 。CPU不会store1与store2进行重排序)
storeload屏障:对于这样的语句store1; storeload; load2 。在load2及后续所有读取操作执行前 。保证store1的写入对所有处理器可见 。(也就是说如果出现storeload屏障 。那么store1指令一定会在load2之前执行,CPU不会对store1与load2进行重排序
② volatile读
文章插图
在每个volatile读操作的后面插入一个LoadLoad屏障 。在每个volatile读操作的后面插入一个loadstore屏障 。
loadload屏障:对于这样的语句load1; loadload; load2 。在load2及后续读取操作要读取的数据被访问前 。保证load1要读取的数据被读取完毕 。(也就是说 。如果出现loadload屏障 。那么load1指令一定会在load2之前执行 。CPU不会对load1与load2进行重排序)
loadstore屏障:对于这样的语句load1; loadstore; store2 。在store2及后续写入操作被刷出前 。保证load1要读取的数据被读取完毕 。(也就是说 。如果出现loadstore屏障 。那么load1指令一定会在store2之前执行 。CPU不会对load1与store2进行重排序)
volatile的实现原理
volatile的实现原理
? 通过对OpenJDK中的unsafe.cpp源码的分析 。会发现被volatile关键字修饰的变量会存在一个“lock:”的前缀 。
? Lock前缀 。Lock不是一种内存屏障 。但是它能完成类似内存屏障的功能 。Lock会对CPU总线和高速缓存加锁 。可以理解为CPU指令级的一种锁 。
? 同时该指令会将当前处理器缓存行的数据直接写会到系统内存中 。且这个写回内存的操作会使在其他CPU里缓存了该地址的数据无效 。
? 具体的执行上 。它先对总线和缓存加锁 。然后执行后面的指令 。最后释放锁后会把高速缓存中的脏数据全部刷新回主内存 。在Lock锁住总线的时候 。其他CPU的读写请求都会被阻塞 。直到锁释放 。
【欢迎随手关注@码农的一天,希望对你有帮助】
其他观点:
从几道相关面试题说起吧 。volatile 常被这么问:
谈谈你对 volatile 的理解?
你知道 volatile 底层的实现机制吗?
volatile 变量和 atomic 变量有什么不同?
volatile 的使用场景 。你能举两个例子吗?
我们知道Java 内存模型——JMM 。JMM是围绕着并发过程中如何处理可见性、原子性和有序性这 3 个 特征建立起来的 。而 volatile 可以保证其中的两个特性 。下面具体探讨下这个面试必问的关键字 。
文章插图
1. 概念
volatile 是 Java 中的关键字 。是一个变量修饰符 。用来修饰会被不同线程访问和修改的变量 。
2. Java 内存模型 3 个特性
2.1 可见性
可见性是一种复杂的属性 。因为可见性中的错误总是会违背我们的直觉 。通常 。我们无法确保执行读操作的线程能适时地看到其他线程写入的值 。有时甚至是根本不可能的事情 。为了确保多个线程之间对内存写入操作的可见性 。必须使用同步机制 。
可见性 。是指线程之间的可见性 。一个线程修改的状态对另一个线程是可见的 。也就是一个线程修改的结果 。另一个线程马上就能看到 。
在 Java 中 volatile、synchronized 和 final 都可以实现可见性 。
2.2 原子性
原子性指的是某个线程正在执行某个操作时 。中间不可以被加塞或分割 。要么整体成功 。要么整体失败 。比如a=0;(a非long和double类型) 这个操作是不可分割的 。那么我们说这个操作是原子操作 。再比如:a++; 这个操作实际是a = a +1;是可分割的 。所以他不是一个原子操作 。非原子操作都会存在线程安全问题 。需要我们使用同步技术(sychronized)来让它变成一个原子操作 。一个操作是原子操作 。那么我们称它具有原子性 。Java的 concurrent 包下提供了一些原子类 。AtomicInteger、AtomicLong、AtomicReference等 。
在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性 。
2.3 有序性
Java语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性 。volatile是因为其本身包含“禁止指令重排序”的语义 。synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock操作”这条规则获得的 。此规则决定了持有同一个对象锁的两个同步块只能串行执行 。
推荐阅读
- 游戏id取名鬼才 过目不忘的游戏id名字
- 丰满和胖有什么不一样?
- 适合8一12岁看的电影 适合孩子看的电影排行榜
- 有没有特别让你惊艳的古言,疯狂想安利给别人的那种?
- 最新全球城市人口排名 世界人口排名一览表图片
- 穿长筒靴搭配光腿神器是不是很难看?
- 腐剧泰国高颜值推荐 高颜值的五部泰国腐剧
- 说出你心中最伟大古代文学作品?理由是什么?
- 男人喜欢的到底是瘦一点的女生,还是有肉感的女生?