volatile 的几点说明

java内存模型(JMM):

其实就是分为两部分,第一部分为主内存区,第二部分为各个线程的本地内存区,当两个线程同时操作某一个变量的时候,会把这个变量从主内存区拷贝到本地内存区,分别在自己的内存中进行操作,同时各个线程之间的本地内存是不可见的,所以会出现线程安全问题。

盗用其他博客的图:

如果连个线程需要通信,那么需要经历以下两个步骤:

1、首先线程A需要把本地内存中的副本刷新到主内存中

2、然后B线程在去住内存中获取A线程刷新的变量

其实JMM 是一个逻辑上的概念,真正的概念是CPU高速缓存(线程本地内存)和内存(主内存之间的关系),也是著名的缓存一致性问题。针对缓存一致性协议和解决方案可以看一下这篇帖子,描述的很好 https://www.cnblogs.com/dolphin0520/p/3920373.html

volatile

volatile 关键字,主要提供一下几个方面的内容

1、保证可见性,但是不保证原子性

2、在一定程度上,可以保证指令重排顺序

现在先来说第一点,当一个变量被volatile修饰的时候,只要对它进行写的操作,就会立即刷新到主内存中,同时其他线程本地内存中会变为无效行,从而得到主内存中最新的值。

从上面的结果可以看出,主线程虽然设置了flag为false,但是由于子线程一直读取的是本都内存中的flag,所以一直不退出循环(这里我不明白,如果不增加休眠,子线程就可以立即退出 why?是因为不增加休眠直接写入主内存了?

当flag增加volatile修饰的时候,在主线程修改之后,会立即同步到主内存中,然后子线程中的flag变为无效,就需要从主内存中同步flag,从而读到新的修改后的数据。这就是其保证可见性的验证。

无法保证原子性是因为,就算线程可以读取到最新的数据,但是无法保证线程内部操作是原子的。代码没有实验出来,以后可以补上。

在一定程度上,可以保证指令重排顺序,借用上面文章的例子,

//x、y为非volatile变量

//flag为volatile变量

x = 2;        //语句1

y = 0;        //语句2

flag = true;      //语句3

x = 4;        //语句4

y = -1;          //语句5

这里1、2会保证一定在3前面执行,4、5保证一定在3后面执行,但是无法保证1、2之间和4、5之间的顺序。

 

至于 volatile 关键字的用途,我不太能想出来在哪里值得一用

1、保证部分代码执行顺序,例如需要初始化,然后dosomething,为了保证dosomething在初始化之后,可以使用 volatile

2、某个线程执行写操作,写完的变量立即让其他线程知道更新后的值,但是其他线程只能读操作。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值