Java控制并发之——volatile关键字
控制并发的三大要素:可见性、原子性、有序性。那么volatile就是控制元素的可见性
下面介绍线程读取量变的过程
描述:
1.假设对象中有一属性:private static int money = 100; 现有2个线程对他进行操作。
2.线程A、B的是从他们各自的线程工作区读取的属性值,工作区的值由主内存得到。
3.现在money 在A、B中各一份,如果A中:money=money-20,此时A中money=80,B中值并未改变money=100;这时A、B两个线程中的money值的变化对方并不知道,所以他们是不可见的。
4.假如这个人账户里只有100块,在A中消费了20,还剩80;又在B中消费了100.就出了大事情了。
5.问题就出在两个线程他们之间是不可见的
解决方案:
1.思考下有没有一个方法,可以让在A中修改的值,让B知道呢?这时候就引出了volatile关键字。
2.它的作用的是让线程每次操作完对象,都把状态更新到主内存中,读取量变也直接从主内存中读取。
3.假如在A中消费20,首先去主内中读取到money=100,再扣除money=money-20,最后放回主内存中。此时B也要消费money,首先去主内中读取到money=80,再扣除消费金额,最后放回主内存中。
4.这样变量money是可见的。
测试:现有2个线程,主线程2秒后停止另一个线程的循环,表面看上去好像没什么问题,但是实际运行中会发现,线程并没有停止下来,这是为什么呢?
public class VolatileTest {
private static Boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (!flag) {
//do something
}
});
thread.start();
Thread.sleep(2000L);
//2秒钟后关闭thread线程
flag = true;
Thread.sleep(100L);
//查看线程是否在运行状态
System.out.println(thread.isAlive());
}
}
可以看到线程还在运行
因为主线程main和thread线程 之间是不可见的,thread并不知道main改了flag变量
解决方案:使用valotile关键字声明可能被多线程共同修改状态的变量
private static Boolean flag = false;
改为
private volatile static Boolean flag = false;
还没有评论,来说两句吧...