Volatile

简介: JUC系列
  1. 特性:内存可见性和防止指令重排(实现线程安全)
  2. 什么是内存可见性

--首先我们要了解在多线程的并发的场景下可能会出现的问题,得先清楚什么JMM(内存模型)
内存模型:在多线程场景下,共享的变量放在主内存空间中,每个线程会开辟一份工作内存空间,将主内存的变量复制一份,各线程操作各自的工作内存空间变量然后写回主内存。
JMM有关同步的规定:

  • 线程解锁前,必须把共享变量的值刷新回主内存;
  • 线程加锁前,必须读取主内存的最新值到自己的工作内存中;
  • 加锁和解锁使用的是同一把锁;

image.png

但这就容易出现缓存一致性问题,为了解决这一问题,可以遵循MESI规范协议(CPU在写数据时,通知其他CUP将该变量的缓存行设置无效,其他CUP在读取变量的时候发现缓存该变量的缓存行无效则重新从主内存读取。)如何发现该变量的缓存行无效呢,这就使用了总线嗅探技术(不间断的判断缓存行对应的内存地址是否发生改变,如果改变则认为无效)
内存可见性就是一个线程修改了主内存的变量后,其他线程立马就知道,并且重新获取更新后的值。

  1. 什么是指令重排

-- 程序最终回转化为指令由CPU去执行,在不改变程序结果的前提下,为了提高性能,编译器和和处理器通常会对指令进行指令重排序,可能执行顺序为:2—1—3—4,也可能是:1—3—2—4,一般分为下面三种:
image.png
禁止指令重排序的原理:因为在volatile会在指令之间插入一条内存屏障指令,通过内存屏障指令告诉CPU和编译器不管什么指令,都不进行指令重新排序。也就说说通过插入的内存屏障禁止在内存屏障前后的指令执行指令重新排序优化。

什么是内存屏障

内存屏障是一个CPU指令,他的作用有两个:

  • 保证特定操作的执行顺序;
  • 保证某些变量的内存可见性;
目录
相关文章
|
8天前
|
缓存 Java 编译器
volatile与synchronized
volatile与synchronized
40 0
|
10月前
|
缓存 Java 编译器
|
10月前
|
Java
浅谈volatile
浅谈volatile
52 0
|
存储 SQL 缓存
|
SQL
volatile的正确使用(七)
volatile的正确使用(七)
88 0
volatile的正确使用(七)
volatile与JMM(二)
问:volatile凭什么可以保证可见性和有序性 答: 内存屏障
75 0
volatile与JMM(二)
|
存储 SQL Java
理解JMM和Volatile
理解JMM和Volatile
106 0
|
缓存
volatile
volatile
81 0
|
SQL 存储 算法
volatile详解
在单线程环境中,我们几乎用不到这个关键词,但是多线程环境中,这个关键词随处可见。而且也是面试的常客。总的来说,volatile有以下三个特性: 保证可见性; 不保证原子性; 禁止指令重排。 下面就来详细的说说这三个特性。
volatile详解
|
存储 缓存 安全
synchronized&volatile (二)
synchronized&volatile (二)
170 0