volatile关键字的作用java

1.内存可见性

        当一个变量被声明volatile时,它会保证被修改的值被立刻更新到主内存中,不会优化到寄存器或缓存中

2.禁止指令重排序

        针对被volatile修饰的变量的读写相关指令,是不能被重新排序的

代码演示

class Counter{
    public int flag;
}
public class Thread3 {
    public static void main(String[] args) throws InterruptedException {
        Counter counter=new Counter();
        Thread t1=new Thread(()->{
           while (counter.flag==0){
               //方便演示什么都不做
           }
        });
        Scanner scanner=new Scanner(System.in);
        Thread t2=new Thread(()->{
           counter.flag=scanner.nextInt();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

上述代码,t1线程在循环检查flag值,成立就执行代码,t2线程更改count值,使得线程1检查结果不成立,测试发现在t2线程代码输入结果后,线程1代码还是不会停止,这是由于t1线程在一个无限循环中检查flag的值,并且flag的更新对t1线程不可见,因此t1线程可能会永远等待下去,即使t2线程已经修改了flag的值。

使用volatile解决

class Counter{
    public volatile int flag; // 声明为 volatile
}
public class Thread3 {
    // ... 其他代码保持不变 ...
}

 使用volatile后

  1. 内存可见性volatile关键字确保了对volatile变量的写操作对其他线程总是可见的。当t2线程更新counter.flag的值时,这个更新会立即对其他线程(如t1线程)可见。这意味着t1线程在检查counter.flag的值时,将总是看到t2线程所做的最新更新。
  2. 禁止指令重排序volatile关键字还禁止了一些可能导致数据竞争的重排序。具体来说,它确保了写volatile变量之前的所有读写操作不会被重排序到写操作之后,同时确保了读volatile变量之后的所有读写操作不会被重排序到读操作之前。这确保了t2线程中的读取输入和更新flag的操作不会被重新排序,从而避免了数据竞争和不一致的行为。

因此,如果将Counter类中的flag字段声明为volatile,那么t1线程将能够正确地看到t2线程对flag的更新,并且不会因为指令重排序而导致数据竞争或不一致的行为。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值