什么是内存模型

  • JMM(Java内存模型)规定了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并发编程的艺术》,里面有大量的章节讲述内存模型的只是,而这本书的这一章节比较晦涩,所以就不细看了。

Java并发编程实战 第16章 Java内存模型的更多相关文章

  1. 《java并发编程实战》读书笔记13--Java内存模型,重排序,Happens-Before

    第16章 Java内存模型 终于看到这本书的最后一章了,嘿嘿,以后把这本书的英文版再翻翻.这本书中尽可能回避了java内存模型(JMM)的底层细节,而将重点放在一些高层设计问题,例如安全发布,同步策略 ...

  2. 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结

    <Java并发编程实战>和<Java并发编程的艺术>           Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...

  3. Java并发编程实战---第六章:任务执行

    废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...

  4. java并发编程实战《二》java内存模型

    Java解决可见性和有序性问题:Java内存模型 什么是 Java 内存模型? Java 内存模型是个很复杂的规范,可以从不同的视角来解读,站在我们这些程序员的视角,本质上可以理解为, Java 内存 ...

  5. 【java并发编程实战】第一章笔记

    1.线程安全的定义 当多个线程访问某个类时,不管允许环境采用何种调度方式或者这些线程如何交替执行,这个类都能表现出正确的行为 如果一个类既不包含任何域,也不包含任何对其他类中域的引用.则它一定是无状态 ...

  6. Java并发编程实战 第8章 线程池的使用

    合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...

  7. Java并发编程实战 第3章 对象的共享

    可见性 可见性是由于java对于多线程处理的内存模型导致的.这似乎是一种失败的设计,但是JVM却能充分的利用多核处理器的强大性能,例如在缺乏同步的情况下,Java内存模型允许编译器对操作顺序进行重排序 ...

  8. JAVA并发编程实战---第三章:对象的共享

    在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当 ...

  9. 【java并发编程实战】第二章:对象的共享

    1.重要的属性 可见性,不变性,原子性 1.1可见性 当一个线程修改某个对象状态的时候,我们希望其他线程也能看到发生后的变化. 在没有同步的情况下,编译器和处理器会对代码的执行顺序进行重排.以提高效率 ...

随机推荐

  1. dvm 的进程和 Linux 的进程, 应用程序的进程是否为同一个概念?

    dvm 指 dalvik 的虚拟机. 每一个 Android 应用程序都拥有一个独立的 Dalvik 虚拟机实例,应用程序都在它自己的进程中运行.而每一个 dvm 都是在 Linux 中的一个进程,所 ...

  2. iOS 图表工具charts之CombinedChartView

    关于charts的系列视图介绍传送门: iOS 图表工具charts介绍 iOS 图表工具charts之LineChartView iOS 图表工具charts之BarChartView iOS 图表 ...

  3. LinkedList简介

    原文:https://blog.csdn.net/GongchuangSu/article/details/51527042 LinkedList简介 LinkedList 是一个继承于Abstrac ...

  4. Java学习笔记之Iterator和ListIterator

    原文:https://blog.csdn.net/GongchuangSu/article/details/51514380 Iterator接口是对collection进行迭代的迭代器,ListIt ...

  5. jquery 教程网

  6. vue v-for直接循环数字

    <svg class="icon" aria-hidden="true" v-for="index of 5" :key=" ...

  7. cocos2dx[3.2](1) 浅析cocos2dx3.2引擎目录

    3.x的引擎目录与2.x的引擎目录的差别是非常大的.3.x主要是将引擎的各个文件按照用途进行了分类,使得引擎目录结构更加清晰了. 从目录中我们主要了解一下以下几个文件: 文件名 说明 build 官方 ...

  8. sql盲注-笔记

     盲注是因为数据库查询的结果不会直接显示在页面.只能通过构造查询语句查看反馈的结果真&假状态来判断信息.   实际注入手法和回显注入区别不大 下面只记录相关思路   select length ...

  9. HDU 1171 Big Event in HDU (动态规划、01背包)

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  10. svn下载项目的时候出现 Path to certificate

    svn关联的时候出现这种情况,并且有svn的账号的时候,可以找setting中Version Control 中的Subversion中celar 一下即可,然后再重新下载就会让你重新输入用户名和密码 ...