关于volatile使用问题

来源:3-4 线程安全性-可见性

坏淡一个

2018-05-05

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

写回答

1回答

Jimin

2018-05-05

你好,有了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
4
李爽爽爽爽
回复
Jimin
谢谢老师,提问的时候还不明白,看到后面的 课程就明白了,谢谢
2018-11-06
共4条回复

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程