java线程可见性

一,为什么有线程可见性的问题

先看看下面这段简单的代码:

public class VolatileTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        while (true) {
               if (myThread.flag) {
                   System.out.println("====================================");
               }
           }
    }

    static class MyThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(100);
                flag = true;
                System.out.println("flag="+flag);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private boolean flag = false;

        public boolean isFlag() {
            return flag;
        }
    }
}

在这里插入图片描述
按道理讲,在线程myThread中已经将flag置为true了,为什么main方法里面的print方法没有执行呢?

就是说子线程的flag值对于main线程是不可见的,这就是线程可见性。

二,线程可见性的根本原因

线程可见性的根本原因在于jvm的内存结构:
在这里插入图片描述

  • 共享变量必须存放在主内存中
  • 线程有自己的工作内存,线程只可以操作自己的工作内存
  • 线程要操作共享变量,需要从主内存中读取到工作内存,改变值后需要从工作内存同步到主内存中

在上面的例子中,flag是共享变量,main方法从主内存中读取flag,而线程myThread从主内存将flag读取到工作内存中,并在工作内存中修改了flag的值,但并没有及时的将flag的值同步回主内存。

三,解决办法

  • 使用volatile关键字
    volatile语义规范:

    • 使用volatile变量时,必须从主内存中加载,并且read、load是连续的
    • 修改volatile变量后,必须立马同步回主内存,并且store、write是连续的

    vilatile关键字的作用:

    • 确保线程可见性
    • 禁止指令重排
  • 将修改flag的代码用synchronized关键字包裹

在这里插入图片描述
或者

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值