JUC多线程(二)、Volatile实现内存可见性的过程和原理(内存屏障)

JUC多线程(二)
学习目标:
●掌握volatile解决内存可 见性的使用
●了解CAS原子操作
●掌握JUC的atomic原子操作包的使用
●了解AQS同步队列的作用
●了解JUC的锁的基本概念
●掌握ReentrantLock和ReentrantReadWriteLock的使用
●掌握Condition的使用

Volatile
通过前面内容我们了解了synchronized ,虽然JVM对它做了很多优化,但是它还是一一个重量级的锁。 而接下来要介绍的volatile则是轻量级的synchronized,如果一个变量使用volatile ,则它比使用synchronized的成本更加低,因为它不会引起线程上下文的切换和调度。
Java语言规范对volatile的定义如下:
Java允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。
通俗点讲就是说一个变量如果 用volatile修饰了,则ava可以确保所有线程看到这个变量的值是一致的,如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立马看到这个更新,这就是内存可见性。
volatile虽然看起来比较简单,使用起来无非就是在一个变量前加上volatile即可,用好并不容易


解决内存可见性问题
在可见性问题案例中进行如下修改,添加volatile关键词:
    private volatile boolean flag = true;

Volatile实现内存可见性的过程
线程写Volatile变量的过程:
    1.改变线程本地内存中Volatile变量副本的值;
    2.将改变后的副本的值从本地内存刷新到主内存
线程读Volatile变量的过程:
    1.从主内存中读取Volatile变量的最新值到线程的本地内存中
    2.从本地内存中读取Volatile变量的副本

Volatile实现内存可见性原理:
写操作时,通过在写操作指令后加入一条store屏障指令,让本地内存中变量的值能够刷新到主内存中
读操作时,通过在读操作前加入一条load屏障指令 ,及时读取到变量在主内存的值
PS:内存屏障( Memory Barrier) 是一种CPU指令 ,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序

volatile的底层实现是通过插入内存屏障,但是对于编译器来说,发现-一个最优布置来最小化插入内存屏障的总数几乎是不可能的,所以, JMM采用了保守策略。如下:
●StoreStore屏障可以保证在volatile写之 前,其前面的所有普通写操作都已经刷新到主内存中。
●StoreLoad屏障的作用是避免volatile写与后面可能有的volatile读/写操作重排序。
●LoadLoad屏障用来禁止处理器把上面的volatile读与下面的普通读重排序。
●LoadStore屏障用来禁止处理器把上面的volatile读与下面的普通写重排序。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值