volatile关键字的作用

本文介绍了在多线程环境下,由于编译器优化可能导致的内存可见性问题,通过一个示例展示了当一个线程修改变量而其他线程无法感知的情况。解决方案是使用Java中的volatile关键字,它可以确保变量在所有线程间保持可见性,避免了编译器优化引起的不安全现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

volatile可用来解决编译器优化代码时带来的多线程不安全问题

问题一: 内存可见性问题

(当有多个线程时,其中一个线程将代码改了, 单另一个线程并没有及时感知到)

造成这种问题的原因是当编译器优化多线程代码时可能会导致读取内存数据时不去主内存即内存(main memory)中读取而是直接去工作内存即CPU寄存器(work memory)中直接取用. 一下是可能引发这种情况的案例

class Counter {
     public int count = 0;
     public void Setcount(int a){
         count = a;
     }
}
public class Sep15thdemo2 {
    static Counter counter = new Counter();
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while(counter.count == 0){//多次读取与比较

            }
        });
        Thread t2 = new Thread(() -> {
            counter.Setcount(1);//将变量count的值修改为1
        });
        t1.start();//启动线程t1
        Thread.sleep(500);//等待线程ti中进行一段时间的对count的读取
        t2.start();//启动线程t2
        t2.join();//等待t2线程中代码执行完毕再往下执行
        System.out.println(counter.count);
    }
}

上述问题主要是当进行多次读取操作时发现count的值未发生改变,编译器就不在去主内存中读取数据.而是直接从工作内存中取数据来语0进行比较,这样省去了读取内存这种开销较大的操作提升了效率,但是当线程t2启动时将内存中count的值由0改为了1,按照我们的预期应该是线程t1中while循环的判断条件由true变为了false应该跳出循环结束进程.但是其结果确实while的循环条件依旧为true程序陷入了循环不会结束.这就是内存可见性所造成的线程不安全

上述情况的解决方法就是利用关键字volatile来阻止编译器对代码的优化,也就避免了内存可见性问题, 使用方法如下

class Counter {
    volatile public int count = 0;//再此处加上volatile关键字就可以防止内存可见性问题
      public void Setcount(int a){
         count = a;
     }
}
public class Sep15thdemo2 {
    static Counter counter = new Counter();
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while(counter.count == 0){//多次读取与比较

            }
        });
        Thread t2 = new Thread(() -> {
            counter.Setcount(1);//将变量count的值修改为1
        });
        t1.start();//启动线程t1
        Thread.sleep(500);//等待线程ti中进行一段时间的对count的读取
        t2.start();//启动线程t2
        t2.join();//等待t2线程中代码执行完毕再往下执行
        System.out.println(counter.count);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值