多线程学习:volatile的作用

一:保证线程可见性

多线程的情况下,有volatile关键字:变量值发生变化,其他线程能实时知道。
多线程读取同一个对象时,每个线程会copy这个对象当前的值存起来用。

1: Demo栗子–有无volatile的区别

public class Demo {

    public volatile boolean running = true;

    public static void main(String[] args) {
        Demo d = new Demo();
        new Thread(d::m1).start();
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        d.running = false;
    }

    public void m1() {
        System.out.println("开始m1方法");
        while (running) {
        }
        System.out.println("结束m1方法");
    }
}

没有volatile关键字时,m1方法不会结束。
存在volatile关键字时,m1方法3秒后会结束。

二:禁止指令重排序

1: new 对象的三部曲

new 一个对象时,分成三步骤,如:String s = new String(“123”);
a: 给对象申请推内存 (int 类型-初始值为0; 引用类型–初始值为null)
b: 成员变量初始化 (将123赋值给s)
c: 栈指向堆内存 (在此之前s对象为null)

2: 指令重排序

现在的cpu是并行执行指令的,可能出现,a完成之后,先执行c步骤,再执行b步骤。
多线程情况下,a、c完成后,b未执行时,拿到的s对象的值为null。
加了volatile之后,能保证a、b、c顺序执行。

三:不能保证原子性,不能替代syc

public class Demo1 {
    volatile int count = 0;

    void m() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }

    public static void main(String[] args) {
        Demo1 d = new Demo1();
        List<Thread> threads = new ArrayList<>();
		//创建10个线程去调用m方法
        for (int i = 0; i < 10; i++) {
            threads.add(new Thread(d::m));
        }

        threads.forEach((o) ->
            o.start()
        );

        threads.forEach(o->{
            try {
                o.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        System.out.println(d.count);
    }
}

打印出来的结果不是100000。
为什么呢?

多线程读取同一个对象时,每个线程会copy这个对象当前的值存起来用。
当一个线程把count变成1,
第二、三个线程读取count 为1,进行了++运算,还没有写回内存
第二个线程执行完,写回去count = 2
此时,第三个线程更新到count = 2,但是第三个线程本身的逻辑执行完了,写回去count 还是 2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值