Volatile理解

Posted jemb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Volatile理解相关的知识,希望对你有一定的参考价值。

java内存模型中,每个线程有自己的工作内存,同时还有一个共享的主内存。

 

为什么要让每个线程都有自己的工作内存呢?

线程运行的代码对应的是一些指令是由CPU执行的!但是CPU每次执行指令运算的时候,要是每次需要一个变量的值,都从主内存加载,性能会比较差!

要是线程的代码在执行过程中,就可以直接从自己本地缓存里加载变量副本,不需要从主内存加载变量值,性能可以提升很多,于是就有了一个工作内存的概念!
 
 
 
每一个线程都有自己的工作内存,并发场景可能遇到的问题?
多个线程并发读写一个共享变量的时候,某个线程修改了变量的值,对其他线程不可见!

 

怎么解决这个问题呢?
可以给变量增加Volidate 关键字修饰,当 线程1对data数据进行修改的时候,强制将data这个变量刷回主存,同时强制其他线程的data变量设置为过期的,获取的时候,需要从主存中获取

技术图片

 

 

技术图片

 

java同步的八种操作:

1.lock(锁定):主内存中,把一个变量标识为一个线程独占的状态

2.unlock(解锁):主内存中,把一个处于锁定状态的变量释放出来

3.read(读取):主内存中,把一个变量从主内存传输到线程的工作内存

4.load(加载):工作内存中,把read操作的从主存中大袋的变量放入工作内存的变量副本中

5.use(使用):工作内存中,把工作内存中的一个变量传递给执行引擎

6.assign(赋值):工作内存中,把一个从执行引擎接收到的值赋给工作内存中的变量

7.store(保存):工作内存中,把工作内存中的变量传送给主内存中,以便进行write的操作

8.write(写入):主内存中,把store操作从工作内存中的变量的值传输到主内存的变量中

 

 

 

Volatile如何保证有序性:

Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序不会影响单线程程序的执行,却会影响到多线程并发的正确性。

Volatile通过内存屏障,防止重排序
  • 在每个volatile写操作的前面插入一个storestore屏障。
  • 在每个volatile写操作的后面插入一个storeload屏障。
  • 在每个volatile读操作的后面插入一个loadload屏障。
  • 在每个volatile读操作的后面插入一个loadstore屏障。

如何保证有序性:Volatile ,Synchronized ,lock

 

 

java内存模型具有先天的有序性,不需要通过任何手段得到保证,如何两个操作不能通过happenBefore原则导出来:

happenBefore原则:

1.程序次序规则:一段程序代码,在单个线程当中,看起来是有序的。

2.锁定规则:一个unlock先行于后面的lock操作

3.volatile变量规则:对一个变量的写操作,先行与读操作

4.传递规则:如果A先行与B,B先行于C,则A先行于C

5.线程启动原则:一个线程必须要执行start方法,才能进行其他操作

6.线程中断原则:不许要执行interrupt()方法,才能检测到有终端事件的发生

7.线程终结规则:线程中的所有操作 先行于他的终止检测

8.对象终结原则:一个对象的初始化,先行于 他的 finalize() 方法的开始

 

Volidate 和Synchronized的区别?
1.Volidate 只保证可见性 ,保证读的时候
2.synchronize 保证可见性和原子性,但是性能稍微差一点
 
 
 
Volidate 为什么不能保证原子性?
如果3个线程 对 主内存的100 读了之后是100
他们分别进行了+1操作后,变成了去101,再写回去的时候 实际就变成了101

 

 

 

以上是关于Volatile理解的主要内容,如果未能解决你的问题,请参考以下文章

对 Volatile.Read/Write 的理解

Java volatile 关键字 理解

JMM及volatile深入理解

想要理解volatile关键字,你只需要掌握它的这三个特点

深入理解Java内存模型——volatile

深入理解Java内存模型——volatile