java关键字之-volatile

浅谈volatile,直接看demo,引出来。

package com.second.app.thread.singleton;

/**
 * @Author soul yzg
 * @Date 2021/2/7 8:22
 * 努力学习 天天进步
 */
public class RunThread extends Thread {

    private boolean isRunning = true;

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean running) {
        isRunning = running;
    }

    @Override
    public void run() {
        System.out.println("进入run了");
        while (isRunning == true) {

        }
        System.out.println("线程要被停止了");
    }
}

package com.second.app.thread.singleton;

/**
 * @Author soul yzg
 * @Date 2021/2/7 8:25
 * 努力学习 天天进步
 */
public class Run {
    public static void main(String[] args) {
        try {
            RunThread runThread = new RunThread();
            runThread.start();
            Thread.sleep(1000);
            runThread.setRunning(false);
            System.out.println("已经被赋值false了");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  • 输出结果:虽然主线程已将isRunning 改成false,但是程序并未停止,一直重复循环,这是什么原因呢?
    在这里插入图片描述
    分析:
    在这里插入图片描述
    如果我们给变量加上volatile关键字修饰,
    在这里插入图片描述
    程序停止了:
    在这里插入图片描述
  • 首先我们了解下线程的原子性,可见性,有序性。
    在这里插入图片描述
  • 对于多个线程之间共享的变量,可以采用volatile关键字修饰,保持可见性。但是volatile不能保证线程的原子性。见下面的代码:
package com.second.app.thread.singleton;

/**
 * @Author soul yzg
 * @Date 2021/2/7 10:32
 * 努力学习 天天进步
 */
public class MyThread extends Thread {

    volatile private static int count;

    @Override
    public void run() {
        addCount();
    }

    private void addCount() {
        for (int i = 0; i < 10; i++) {
            count++;
        }
        System.out.println(Thread.currentThread().getName()+"count=" + count);
    }
}
package com.second.app.thread.singleton;
/**
 * @Author soul yzg
 * @Date 2021/2/7 8:25
 * 努力学习 天天进步
 */
public class Run {
    public static void main(String[] args) {
        //自定义线程数组,模拟10个线程
        //假设volatile符合原子性,那么10个线程最终计算的count的值应该等于100;
        MyThread[] threadArray = new MyThread[10];
        for (int i = 0; i < 10; i++) {
            threadArray[i] = new MyThread();
        }
        for (int i = 0; i < 10; i++) {
            threadArray[i].start();
        }
    }
}

实则不然:
在这里插入图片描述

  • 我们会发现:最终的结果并不等于100;那么如何在保持原子性呢?
    答:只需要引入synchronized关键字,保持同步,因为count++并不是原子性操作,所以需要保证同一 个时刻只有一个线程进行++操作。如下:
    在这里插入图片描述
    在这里插入图片描述
    下面摘抄来自:高红岩的多线程编程核心艺术。
    在这里插入图片描述
    在这里插入图片描述

谈到volatile关键字,不得不谈指令重排,因为volatile是禁止指令重排的。

  • 说到这里,我对指令重排还是有点迷糊的,说到底平时开发中一般对计算机底层接触的比较少。利用这个春节放假间隙,我慢慢完善。因为真的很少去总结。
  • 指令重排:我的理解为计算机在执行程序代码的一种方式。cpu处理器和编译器为了提高性能,默认会对代码进行一定的重排。
  • 单线程情况下,确保程序的执行结果和和代码顺序执行结果保持一致。
  • 但是在多线程的情况下,由于指令重排的存在,所以不能保证两个线程使用的变量保持一致。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值