java中的volatile关键字日常用法实践

本文总结了《深入理解Java虚拟机》中volatile关键字的用法,并通过代码示例解释了其可见性和禁止指令重排序的特性。

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


前言

本篇文章主要记录在读完《深入理解Java虚拟机》中对volatile关键字的用法后,进行个人消化后的总结和代码实践。


一、volatile关键字的语义?

  • 可见性,子线程修改变量,值立即回写到主内存,其他线程不读取副本而是直接从主内存读取新值。
  • 禁止指令优化重排序。

二、举例实践

1.可见性

代码如下(示例):

public class Demo {

    private static volatile boolean flag = false;
    public static ExecutorService executor = Executors.newFixedThreadPool(20);

    public static void main(String[] args) throws Throwable{

        for (int i = 0; i <100 ; i++) {
            executor.submit(new Thread(new Runnable() {
                @Override
                public void run() {
                    while (!flag){

                    }
                }
            }));
        }

        //保证线程都启动完毕
        Thread.sleep(500);
        flag = true;

        executor.shutdown();
        executor.awaitTermination(100, TimeUnit.SECONDS);
        System.out.println("完成!");

    }

变量flag用volatile声明,程序会正常结束,打印“完成!”。
变量flag不用volatile声明,程序无法结束。

2.DCL单例模式中禁止指令重排序

代码如下(示例):

public class Singleton {

	
    private static volatile Singleton instance=null;

    public static Singleton getInstance() {
        if(null == instance){
            System.out.println("1");
            synchronized (Singleton.class){
                if(null == instance){
                    System.out.println("2");
                    instance = new Singleton();//如果不用volatile修饰instance,这一步在编译成字节码后,很有可能发生指令重排序,造成返回一个未初始化完成的对象。
                }
            }
        }
        return instance;
    }

}

并发量到一定地步可以模拟返回一个未初始化完成的对象现象 ,本机模拟不到。

这个现象涉及到java内存模型中对象的创建语句在字节码中指令重排序。

总结

虽然掌握了volatile一些常用场景的用法,和一些发生线程非安全的原因,但是要彻底掌握,需要对java内存模型,对象创建,以及对虚拟机字节码重排序有深入了解,在今后的工作中,如果有时间再补充这块知识进行加深印象。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值