请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于volatile使用问题

https://img1.sycdn.imooc.com//szimg/5aecffd300014a4b08060665.jpg
还是不理解使用volatile有什么好处?就算现在没有volatile修饰,等线程1执行完成后将值写入主内存,线程2再判断为true然后执行,除了慢一点点也没什么影响啊

正在回答

1回答

Jimin 2018-05-05 11:05:42

你好,有了volatile,一旦别的线程修改,这里可以得到最新的值,也能避免某些重排序。

线程1把写入主内存后,线程2如果之前已经执行了while(!inited) 判断时,那么你是无法确定线程2什么时候可以读到最新的主内存里的值的,而不是简单的慢一点点的。这里的写法也是期望在inited变成true时立刻开始执行后面的程序。

这是第一个原因,再说第二个原因,也是一个更重要的原因。如果不加volatile,线程1的两段代码可能发生重排序,就是先执行inited=true, 再执行context=loadContext(), 这样一来就会出现inited=true时,context还有短暂为空的一段时间。这时如果线程2执行时发现inited为true了,去执行doSomethingWithConfig(context)时,就会出现操作的是一个空值了,这个明显不符合预期。而线程2之前的循环判断就是为了保证loadContext()肯定执行。这时有了volatile就不一样了,他可以保证线程1先执行context=loadContext(),再执行inited=true,之后线程2才可能执行到doSomethingWithConfig(context)。保证代码执行符合预期。

我们在处理涉及到多线程共享的变量时,很多情况下需要读到变量准确的值和避免重排序,尽可能的保证当前线程的执行符合预期。这个例子还算简单,复杂一点的,有时你使用了过期的变量的值,而你以为你拿到的最新的值,就可能会导致代码的执行远离你的预期,导致程序执行出错,也可能带来很大的损失。

而为了避免这个问题,jvm里定义了volatile关键字,在需要的时候使用它,利用它的可见性及避免重排序,来尽可能保证代码按照你的预期执行。


3 回复 有任何疑惑可以回复我~
  • 精彩!!
    回复 有任何疑惑可以回复我~ 2018-06-29 14:48:07
  • 老师,您好,这里有个地方不明白,请问为什么会发生重排序啊……也就是线程一为什么先执行第二句,再执行第一句
    回复 有任何疑惑可以回复我~ 2018-11-06 11:08:26
  • 两行代码如果没什么关联的话,对应cpu的指令也会没什么关联,对于计算机而言,先执行哪个都可以(对于我们而言也是这样),因此在执行时可能会做一些优化,就是重排序。可是很不幸的是,一旦重排序,多线程下就会有问题,就是课程里说的这种case,因此需要引入锁、volatile等限制某些重排序。
    回复 有任何疑惑可以回复我~ 2018-11-06 12:10:54
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信