zoukankan      html  css  js  c++  java
  • Java并发编程实战 第16章 Java内存模型

    什么是内存模型

    • JMMJava内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见。
    • JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Before。两个操作缺乏Happens-Before关系,则Jvm会对它们进行任意的重排序。

      Happends-Before的规则包括:

      1. 程序顺序规则。若程序中操作A在操作B之前,则线程中操作A在操作B之前执行。

      2. 监视器锁规则。在同一监视器锁上的解锁操作必须在加锁操作之前执行。如图所示,

      3. volatile变量规则。对volatile变量的写操作必须在读操作之前执行。

      4. 线程启动规则。Thread.start必须在线程中执行的操作之前被调用。

      5. 线程关闭规则。线程中的任何操作必须在其他线程检测到该线程结束之前执行,或者从Thread.join中返回,或调用Threas.isAlive返回false。

      6. 中断规则。当一个线程在另一个线程上调用interrupt时,必须在被中断线程检测到interrupt调用之前执行。

      7. 终结器规则。对象的构造函数必须在启动该对象的终结器之前执行完成。

      8. 传递性。如果操作A在操作B之前执行,操作B在操作C之前执行,则操作A必须在操作C之前执行。

      双重检查加锁

    1. /**
    2.  * 双重检查加锁, 不安全,
    3.  * 线程可能看到无效的值, 可加上volatile修饰
    4.  */
    5. public class DoubleCheckedLocking {
    6.     private static Object resource;
    7.  
    8.     public static Object getInstance(){
    9.         if (resource == null){
    10.             synchronized (DoubleCheckedLocking.class){
    11.                 if (resource == null){
    12.                     resource = new Object();
    13.                 }
    14.             }
    15.         }
    16.         return resource;
    17.     }
    18. }

    如果不使用volatile,可能看到对象的错误或者无效状态。

    原因:因为JMM会在发布对象的引用和内部构造函数之间进行重排序,也就是说先把栈中对象的引用指向堆中的位置,但是由于重排序堆中的构造函数还没有执行完。但是使用volatile可以避免这种重排序。

    因为接下来要看《Java并发编程的艺术》,里面有大量的章节讲述内存模型的只是,而这本书的这一章节比较晦涩,所以就不细看了。

  • 相关阅读:
    Firefox for macOS 标签关闭按钮设置在左侧
    Nginx 非编译安装 stream 模块实现四层负载均衡
    苹果手机卡死,强制关机方法
    Git安装完成,文件夹下右键菜单不出现出现Git Bash Here 和Git UI Here问题
    AESUtil
    若依框架清空select2选择
    RSAUtils
    springboot 延时任务
    Mqtt的坑,真的坑
    springboot 支付宝支付业务网页端扫码
  • 原文地址:https://www.cnblogs.com/xiaolang8762400/p/7075301.html
Copyright © 2011-2022 走看看