java 修改内存变量_Java内存模型与volatile关键字

原标题:Java内存模型与volatile关键字

Java的内存模型大概样子还是有必要了解下的,今天就学习了下,顺便学习了一点volatile关键字!

Java内存模型

5588142b7542df43b99d6801ab8d09f7.png

主内存中存储一些可以共享的变量比如实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为它们是线程私有的,不会被共享。

每个线程获取这类变量都是先把变量从主内存加载到工作内存,然后才能进行使用,同样如果是修改,那么也是先修改了工作内存中的变量,然后再从工作内存同步进主内存中。

多线程不安全

这种模式就会出现多线程不安全问题,如果两个线程同时操作数据,如下图:

e781bf8a11bb38ce572e58913f30ffa2.png

两个线程同时对主内存中变量进行操作,他们都会把变量先加载到自己的工作内存中去,然后对他进行操作,如果并发执行,线程2就会覆盖线程1的操作。

关键字volatile

一个变量如果被volatile修饰那么他有两个特性:

1、变量对所有线程的可见性,意思是如果一条线程修改了这个变量的值,那么其他线程就可以立刻知道的。

2、禁止指令重排序优化,JVM在编译Java代码、或者CPU在执行JVM字节码时,对现有的字节码指令顺序进行重新排序。

特性1的可见性解释如下图:

952ad6b026f150b2700bfd0e25d1207c.png

volatile修饰的变量在被修改后会处理器直接将结果stroe和write进主内存,同时使得其他线程的工作内存缓存失效,这样就实现了所谓的可见性!

volatile同样不安全

但是如果这样就能保证数据的安全了吗?请看下面的示例:

379bab73a15fc2eebfc0409dbce9dcf7.png

30个线程都对共享变量shareVariable进行了10000次自增。但是最终的打印结果却不是30*10000,这是因为volatile只保证了变量的可见性,并不保证变量的原子性。

通过之前的字节码学习,我们知道“i=i++”需要用到多行字节码指令,并且一个字节码指令可能包含不止一条机器码指令,因此“i=i++”并不具有原子性。所以shareVariable变量并没有达到我们想要的结果。

也就是说即使通过volatile把变量的修改及时同步到其他线程的工作内存,但是由于对变量的操作并不是原子行,比如最简单的“shareVariable++;”可以看下他的字节码如下图:

f7b04c2bf7b26ecf46888b12656a38dc.png

在字节码层面也经历了:从常量池加载i,加载常量1,然后add指令对他们计算,再put进常量池中,一共4个步骤,而机器码就更加多了。

volatile使用场景

那么volatile这个字段又有什么用呢?

01eb0ef74b59df2167d342c209605c64.png

由于volatile变量只能保证可见性,并不能保证原子性,不过在以下场景还是可以使用的:

1、运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。

2、变量不需要与其他的状态变量共同参与不变约束。

第一条保证了变量的准确性,第二条则是防止变量参与约束时又产生原子性问题,比如上面那个代码“if (shareVariableBoolean)”再加一些判断条件,新加的条件可能就会破坏原子性问题。

所以在不符合以下两条规则的运算场景中,我们还是要通过加锁 (使用synchronized、java.util.concurrent中的锁或原子类)来保证原子性。

总结

今天只是简单的了解了下Java的内存模型和volatile关键字,不过也知道了volatile关键字并不能保证线程安全,但是在面试中好像经常有这一问!

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

责任编辑:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值