并发编程知识梳理(六)

文章讨论了Java中的volatile关键字在内存可见性方面的应用,强调了它如何确保共享变量的即时更新。同时指出volatile不能保证原子性,对于需要线程安全的操作,如increase方法,需配合synchronized使用。

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

二、JMM

2、volatile内存语义

volatile是Java虚拟机提供的轻量级的同步机制。volatile关键字有如下两个作用

  • 保证被volatile修饰的共享变量对所有线程总数可见的,也就是当一个线程修改了一个被volatile修饰共享变量的值,新值总是可以被其他线程立即得知。volatile不能保证原子性

    public class VolatileVisibilitySample {
        volatile boolean initFlag = false;
        public void save(){
            this.initFlag = true;
            String threadname = Thread.currentThread().getName();
            System.out.println("线程:"+threadname+":修改共享变量initFlag");
        }
        public void load(){
            String threadname = Thread.currentThread().getName();
            while (!initFlag){
                //线程在此处空跑,等待initFlag状态改变
            }
            System.out.println("线程:"+threadname+"当前线程嗅探到initFlag的状态的改变");
        }
        public static void main(String[] args){
            VolatileVisibilitySample sample = new VolatileVisibilitySample();
            Thread threadA = new Thread(()->{
                sample.save();
            },"threadA");
            Thread threadB = new Thread(()->{
                sample.load();
            },"threadB");
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            threadA.start();
        }
    }
    
    /*并不是说不添加volatile就一定不能被感知,只是说加上volatile能保证马上感知,比如说我不添加volatile关键字,但是我在while (!initFlag){中添加一个sout,或者其他操作同样有可能感知到*/
    

    在线程A改变了initFlag的属性之后,线程B能马上感知

    //示例
    public class VolatileVisibility {
        public static volatile int i =0;
        public static void increase(){
            i++;
        }
    }
    

    volatile无法保证原子性:

    在并发场景下,i变量的任何改变都会立马反应到其他线程中,但是如此存在多条线程同时调用increase()方法的话,就会出现线程安全问题,毕竟i++;操作并不具备原子性,该操作是先读取值,然后写回一个新值,相当于原来的值加上1,分两步完成,如果第二个线程在第一个线程读取旧值和写回新值期间读取i的域值,那么第二个线程就会与第一个线程一起看到同一个值,并执行相同值的加1操作,这也就造成了线程安全失败,因此对于increase方法必须使用synchronized修饰,以便保证线程安全,需要注意的是一旦使用synchronized修饰方法后,由于synchronized本身也具备与volatile相同的特性,即可见性,因此在这样种情况下就完全可以省去volatile修饰变量。

  • 禁止指令重排序优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值