并发编程(一):volatile关键字

一:JAVA内存模型

涉及到的知识点:

多级缓存,MESI协议,缓存一致性协议,总线嗅探机制,原子性操作(8种原子操作)

 volatile 关键字的主要作用就是保证变量的可见性然后还有一个作用是防止指令重排序。为什么?

扫描二维码关注公众号,回复: 10899303 查看本文章

可见性:MESI协议(一种支持写回策略的缓存一致性协议)和总线嗅探机制决定了volatile能保证可见性;

详细解释:MESI协议,规定了哪些情况下将工作内存(也可以说缓存)中数据写回主内存,而总线嗅探机制,是比较工作内存(缓存)中变量与主内存中变量是否一致。结合来说,就是MESI协议规定工作内存写操作执行时会同步刷新主内存的变量值,而总线嗅探机制则判断写操作的当前变量值是否与主内存一致,若一致,则可以进行写操作(表明主内存变量值未被其他线程修改)。

MESI协议:Modified,Exclusive,Shared,Invalid;一种支持写回策略的缓存一致性协议。

MESI协议详细参见:https://www.cnblogs.com/yanlong300/p/8986041.html

防止指令重排:原因是内存屏障

详细解释:内存屏障包括Store Memory Barrier(写内存屏障),Load Memory Barrier(读内存屏障);对应原子操作是store和load;

lock:解锁时,jvm会强制刷新cpu缓存,导致当前线程更改,对其他线程可见。

volatile:标记volatile的字段,在写操作时,会强制刷新cpu缓存,标记volatile的字段,每次读取都是直接读内存。(StoreLoad Barriers)

final:即时编译器在final写操作后,会插入内存屏障,来禁止重排序,保证可见性

二:并发编程的三个重要特性

  1. 原子性 : 一个的操作或者多次操作,要么所有的操作全部都得到执行并且不会受到任何因素的干扰而中断,要么所有的操作都执行,要么都不执行。synchronized 可以保证代码片段的原子性。
  2. 可见性 :当一个变量对共享变量进行了修改,那么另外的线程都是立即可以看到修改后的最新值。volatile 关键字可以保证共享变量的可见性。
  3. 有序性 :代码在执行的过程中的先后顺序,Java 在编译器以及运行期间的优化,代码的执行顺序未必就是编写代码时候的顺序(指令重排)。volatile 关键字可以禁止指令进行重排序优化。

三:synchronized 关键字和 volatile 关键字的区别

  • volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。
  • 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞
  • volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。
  • volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

发布了27 篇原创文章 · 获赞 0 · 访问量 9932

猜你喜欢

转载自blog.csdn.net/weixin_38246518/article/details/105543158
今日推荐