关于可见性

t线程中有一个while-true循环,我们试图通过在主方法中将run置为0,让t线程停下来,但是执行程序我们发现,并没有和我们预想的一样,t线程会停下来

尝试分析这个过程

初始状态,t线程刚开始从主内存读取了run的值到工作内存

因为t线程要频繁的从主内存中读取run的值,JIT编译器会将run的值缓存至自己内存中的高速缓存中(底层是CPU中的缓存),减少对主存中run的访问,提高效率 

 一秒之后,main线程修改了run的值,并同步至主内存,而t是从自己工作内存中的高速缓存中读取这个变量的值,结果依然是旧值

解决方案就是在run这个值加一个volatile关键词修饰,它可以用来修饰成员变量和静态成员变量,它可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值, 线程操作volatile变量都是直接操作主存

synchronized也可以完成这一工作

 也和我们预想的一样停止了,说明synchronized也可以保持可见性,但是synchronized会创建监视器,属于重量级的锁,volatile就更轻量,推荐使用volatile。

可见性和原子性

上述的例子体现的就是可见性,它保证的是多个线程之间,一个线程对volatile变量的修改对另一个线程可见,不能保证原子性,仅用在一个写线程,多个线程读的情况,依然无法解决指令交错的情况发生。

synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性,但缺点是synchronized是属于重量级操作,性能相对更低。

但是如果在前边示例的死循环中加入System.out.println()会发现即使不加volatile修饰符,线程t也能正确看到对run变量的修改。

因为print方法加了synchronized关键字(当然println也加了,换行操作也会持有锁)
而synchronized方法也是能保证了该同步块中的变量的可见性的,所以下次stop从主存中读出false就跳出了while。
这里记录一下synchronized做的操作:
1、获得同步锁;
2、清空工作内存;
3、从主内存拷贝对象副本到工作内存;
4、执行代码(计算或者输出等);
5、刷新主内存数据;
6、释放同步锁。
总结一句话:sychronized可以保证变量的可见性

 

 

  

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值