zoukankan      html  css  js  c++  java
  • java面试总躲不过的并发(二):volatile原理 + happens-before原则

    一.happens-before原则

    同一个线程中的,前面的操作 happens-before 后续的操作。(即单线程内按代码顺序执行。但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进行重排序,这是合法的。换句话说,这一是规则无法保证编译重排和指令重排)。

    1. 监视器上的解锁操作 happens-before 其后续的加锁操作。(Synchronized 规则)

    2. 对volatile变量的写操作 happens-before 后续的读操作。(volatile 规则)

    3. 线程的start() 方法 happens-before 该线程所有的后续操作。(线程启动规则)

    4. 线程所有的操作 happens-before 其他线程在该线程上调用 join 返回成功后的操作。

    5. 如果 a happens-before b,b happens-before c,则a happens-before c(传递性)

    二.volatile关键字的作用

    Volatile关键字主要用于保证内存可见性和顺序性:

    1.volatile修饰的变量可以保证一个线程对该变量的写happens-before 一个线程对该变量的读

    2.Volatile可以用来修饰long和double类型的变量使其以原子方式执行

    3.Volatile在双重检查加锁的单例模式中的应用,可以防止重排序

    java面试总躲不过的并发(二)

     

    三.volatile关键字的实现原理

    在java代码编译成字节码时会在volatile修饰的共享变量进行写操作的时候会多出Lock前缀的指令。

    我们知道为了提高处理速度,CPU不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,但操作完不知道何时会写回内存。如果对声明了volatile的变量进行写操作,JVM就会向CPU发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。所以,在多处理器下,为了保证各个CPU的缓存是一致的,就会实现缓存一致性协议,每个CPU通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前CPU的缓存行设置成无效状态,当CPU对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里

    1. Lock前缀的指令会引起CPU缓存写回内存;
    2. 一个CPU的缓存回写到内存会导致其他处理器的缓存失效;
    3. 当CPU发现本地缓存失效后,就会从内存中重读该变量数据,即可以获取当前最新值。

    这样针对volatile变量通过这样的机制就使得每个线程都能获得该变量的最新值

    volatile相关的理解就写到这里,如果大家还想详细的了解volatile可以查阅相关资料或者私信我进行交流。

    并发是java中无法避免的问题,基本上java面试都会涉及一些并发相关的问题,尤其是互联网公司一定会问到,今天就先写到了这里,下次准备把并发中相关的锁和并发集合的知识整理一下分享给大家,如果喜欢记得关注我【不爱八阿哥】,有什么问题也可以私信交流,让我们共同进步。

    来源:https://www.toutiao.com/i6656572928701760004/

  • 相关阅读:
    mysql 导入报错(ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_E)
    Docker容器开机自动启动
    linux 查看内存条详情命令
    Linux 网络性能测试工具 iperf 的安装和使用
    redis基准性能测试
    pmm的安装,这里推荐下载官方提供的脚本,直接执行这个脚本就可以完成安装
    mysqlslap压力测试时出现"Can't connect to MySQL server"
    Linux监控工具介绍系列——iostat
    提高RabbitMQ的File descriptors
    python 打包
  • 原文地址:https://www.cnblogs.com/hahajava/p/10570959.html
Copyright © 2011-2022 走看看