volatile-详解

首先见下代码:

在下面的代码中,首先有一个多线程类,类中有共享数据flag,默认初始值为false;

程序启动后首先创建了一个thread子线程,在子线程中的逻辑是等待了200毫秒后将flag修改成了true,并打印flag的值

同时在主线程中进入while(true),判断flag的值是否为true,为true则打印flag的值并退出循环

 

public class VolatileDemo {
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        new Thread(threadDemo).start();
        while (true) {
            if (threadDemo.isFlag()) {
                System.out.println("main-flag=" + threadDemo.isFlag());
                break;
            }
        }
    }
}
class ThreadDemo implements Runnable {
    private boolean flag = false;
    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag=" + flag);
    }
    public boolean isFlag() {
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

这段代码的最终输出结果为:并且jvm虚拟机一直未退出,因为程序一直在while循环中未结束。

flag=true

问题:

此时就会发现问题,明明在子线程中已经将flag修改成true了,但是在主线程中flag的值还是false,这就是内存可见性的问题

原因:

这个问题的原因是内存可见性的问题。

由于在程序运行的时候jvm会为每个线程都分配一个独立的内存用作缓存来提高效率。当程序启动的时候jvm就会为main主线程和ThreadDemo子线程分别分配独立的内存空间,且初始的时候flag在主内存中,且是false的状态;在子线程启动后,程序立即暂停了200毫秒,所以main主线程先执行了,主线程先从主存中获取了flag的值为false;然后子线程从主存中获取了flag的值然后修改了flag的值并且打印了flag的值,之后回写到了主存中。main主线程中while(true)的代码是较为底层的逻辑,执行效率非常高,导致一直无法从主存中获取到最新的flag的值,所以while中的if判断一直未false。

所以就出现了内存可见性的问题,简而言之,当线程操作共享数据时,各个线程的最新值彼此不可见。

解决方式1:

加锁:

while (true) {
    synchronized (threadDemo) {
        if (threadDemo.isFlag()) {
            System.out.println("main-flag=" + threadDemo.isFlag());
            break;
        }
    }
}

将while中的代码加上synchronized互斥锁,使用这个关键字来确定当前线程中的所以共享变量都是从主存中获取到的最新结果

缺点:由于互斥锁的关系,当一个线程在执行的时候,其他线程将会等待,就会出现效率低下的问题。

解决方式2:

使用volatile关键字

private volatile boolean flag = false;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值