Java控制并发之——volatile关键字

痛定思痛。 2022-04-10 04:26 299阅读 0赞

控制并发的三大要素:可见性、原子性、有序性。那么volatile就是控制元素的可见性
下面介绍线程读取量变的过程
在这里插入图片描述

  1. 描述:
  2. 1.假设对象中有一属性:private static int money = 100; 现有2个线程对他进行操作。
  3. 2.线程AB的是从他们各自的线程工作区读取的属性值,工作区的值由主内存得到。
  4. 3.现在money AB中各一份,如果A中:money=money-20,此时Amoney=80B中值并未改变money=100;这时AB两个线程中的money值的变化对方并不知道,所以他们是不可见的。
  5. 4.假如这个人账户里只有100块,在A中消费了20,还剩80;又在B中消费了100.就出了大事情了。
  6. 5.问题就出在两个线程他们之间是不可见的
  7. 解决方案:
  8. 1.思考下有没有一个方法,可以让在A中修改的值,让B知道呢?这时候就引出了volatile关键字。
  9. 2.它的作用的是让线程每次操作完对象,都把状态更新到主内存中,读取量变也直接从主内存中读取。
  10. 3.假如在A中消费20,首先去主内中读取到money=100,再扣除money=money-20,最后放回主内存中。此时B也要消费money,首先去主内中读取到money=80,再扣除消费金额,最后放回主内存中。
  11. 4.这样变量money是可见的。

测试:现有2个线程,主线程2秒后停止另一个线程的循环,表面看上去好像没什么问题,但是实际运行中会发现,线程并没有停止下来,这是为什么呢?

  1. public class VolatileTest {
  2. private static Boolean flag = false;
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread thread = new Thread(() -> {
  5. while (!flag) {
  6. //do something
  7. }
  8. });
  9. thread.start();
  10. Thread.sleep(2000L);
  11. //2秒钟后关闭thread线程
  12. flag = true;
  13. Thread.sleep(100L);
  14. //查看线程是否在运行状态
  15. System.out.println(thread.isAlive());
  16. }
  17. }

可以看到线程还在运行
因为主线程main和thread线程 之间是不可见的,thread并不知道main改了flag变量

在这里插入图片描述
解决方案:使用valotile关键字声明可能被多线程共同修改状态的变量

  1. private static Boolean flag = false;
  2. 改为
  3. private volatile static Boolean flag = false;

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,299人围观)

还没有评论,来说两句吧...

相关阅读