大厂面试(四)请说明volatile的作用?—美团

面试造火箭,工作拧螺丝。相信所有的朋友面试都会被问到特别底层的东西,问到你怀疑人生,而工作中完全用不到,为什么呢?

我认为原因有三:

  1. 岗位竞争激烈

    随着这个行业人才饱和,入门门槛越来越高,与其招你进来都是拧螺丝,那我还不如看看能不能招到造火箭的呢

  2. 挖掘潜力

    拧螺丝永远是拧螺丝的,对技术的掌握程度决定了你在公司以后能走到什么样的位置

  3. 对技术的追求

    对于一种技术,你只是会用,而没有去深度挖掘,说明你对技术没有那么热爱,那么公司也不会放心让你去工作。

互联网三高是哪三高

  1. 高血压
  2. 高血脂
  3. 高血糖

开个玩笑~

  1. 高可用
  2. 高性能(高并发、低延迟)
  3. 高扩展

volitile的作用

保持线程可见性

先来看个小程序

private static boolean running = true;

public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
        while (running) {
            
        }
        System.out.println("end...");
    }).start();
    Thread.sleep(1000);

    running = false;
}

这个程序有个静态变量,默认是true,启动一个线程,里面有个循环,只要running为true就会一直while循环,然后下面我sleep1秒,running的值改为false,这时候程序会输出end…吗?

你会发现,程序1s后依然在运行,没有输出end…,为什么?我明明已经给running赋值为false了。

因为JVM里,你的静态变量在主内存里初始化值为true,当你new一个线程的时候,会把主内存的这个值拿到线程私有内存中存起来,每次都会读线程本地的这个值,不会去主内存中同步新的值,就算你有其他的线程把主内存的值改成false了,你读到的依然是本地的值,所以程序是不会输出end…的。

这个时候我在running上加个volatile关键字,再看下结果

private static volatile boolean running = true;

public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
        while (running) {

        }
        System.out.println("end...");
    }, "server").start();
    Thread.sleep(1000);

    running = false;
}

程序在1s后输出了end…,说明了什么?volatile关键字修饰的是主内存中的running,它的作用是保持线程可见性,它会让这个线程每次都从主内存中取值。

禁止指令重排序

什么叫指令重排序?CPU的效率要比内存的效率高100倍,假如有一个CPU和一块内存,CPU有两条指令要执行,第一条 x+1,第二条 y+1,这两条指令互不相关,以前CPU执行的时候是按顺序执行的,等指令一执行完以后再执行指令二,而内存的效率又非常慢,这就导致CPU的效率发挥不到极致,所以CPU就做了优化,既然是两条互不影响的指令,那我为什么非要等指令一执行完再去执行指令二呢,我也可以先执行指令二,再执行指令一,这样就会整体提升效率,这就是指令重排序。

比如你想喝茶,你需要先洗水壶–>烧开水–>洗茶壶–>洗茶叶–>拿茶杯–>泡茶–>喝茶,指令重排序就是在你烧开水的过程之中,我把洗茶壶、洗茶杯、拿茶杯的事全干了,效率就提升了。

在JVM中有8种情况是不允许指令重排序的,这是JVM的规定。比如必须先new一个对象然后才可以GC。

怎么证明指令重排序的存在?

private static int x = 0, y = 0;
private static int a = 0, b = 0;

public static void main(String[] args) throws InterruptedException {
    int i = 0;
    while (true) {
        i++;
        x = 0; y = 0;
        a = 0; b = 0;
        Thread one = new Thread(()->{
            a = 1;
            x = b;
        });
        Thread other = new Thread(()->{
            b = 1;
            y = a;
        });
        one.start();
        other.start();
        one.join();
        other.join();
        String result = "第"+i+"次("+x+","+y+")";
        if (x == 0 && y == 0) {
            System.out.println(result);
            break;
        }
    }
}

这个程序就能证明指令重排序真的存在,这是一个死循环,里面有4个变量,两个线程分别对它们赋值,如果指令重排序不存在,那么先写的先执行,后写的后执行,x和y不可能同时等于0,只有同时执行第二句才可能出现x=0,y=0。

那volatile是如何禁止指令重排序的呢?

下篇文章说一下美团的一个面试题,**DCL到底需不需要volatile?**这篇文章会解释volatile是如何禁止指令重排序的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YoungJ5788

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值