Java并发编程的艺术-java内存模型读书笔记

Java内存模型java

1 线程之间如何通讯缓存

1.1 共享内存的方式多线程

    1.1.1 处理器写缓存区app

    1.1.2 总线jvm

    1.1.3 共享内存函数

1.2 消息传递的方式优化

    1.2.1 线程之间没有公共状态,必需经过消息的方式通讯ui

2 从源代码到指令序列的重排序线程

2.1 重排序分类rest

    2.1.1 编译器优化重排序

    2.1.2 处理器重排序

        2.1.2.1 内存系统重排序

        2.1.2.2 指令级并行重排序

2.2 重排序的影响

    2.2.1 单线程中,不影响线程运行结果,给你的幻觉是,它不存在

    2.2.2 多线程中,无形中影响运行结果,也是让人产生错觉

2.3 禁止特定类型的重排序

    2.3.1 内存屏障

        2.3.1.1 loadlaod

            2.3.1.1.1 load1 loadlaod load2,确保load1数据的装载先与load2及之后的全部数据装载指令的执行

        2.3.1.2 loadstore

            2.3.1.2.1 load1 loadstone store1 确保laod1数据的加载先与store1以及后面全部存储指令刷新内存

        2.3.1.3 storestore

            2.3.1.3.1 store1 stroestore store2 确保store1的存储指令(属性内存)先有store2以及后面的全部存储指令的刷新内存

        2.3.1.4 storelaod

                2.3.1.4.1 store storeload load store 确保store的存储指令先与load以及后面全部的装载操做

    2.4 单线程的重排序 as-if-serial

            2.4.1 单线程在不改变运行结果的状况下,多有的 编译器,runtime,处理器都会遵循as-if-serial语义进行重排序

3 数据竞争

3.1 一个线程在写一个变量,另一个线程在读一个变量,而两个线程没有经过同步来排序

4 顺序一致性

4.1 科学家意淫出来的模型

4.2 多个线程按顺序执行、单个线程内部按指令顺序执行

5 JMM中的顺序一致性

5.1 多个线程按照顺序执行,边界内部重排序执行

5.2 long与double型数据写操做不具有原子性

      5.2.1 在计算机中,数据经过总线在处理器与内存中交互。每次交互的多个操做,称做一个总线事务,而总线会同步事务,一个时刻,只有一个线程与内存交互,串行化了多个处理器对内存的访问,在某些处理器中,要保证64位数据的写操做会有比较大的开销,这样,妥协以后,java内存模型,鼓励可是不强求jvm对64位long和double具备原子操做,这样一次写,会落在两个事务中,此时就不具备原子性了

6 volatile的内存语义

6.1 volatile特性

    6.1.1 内存可见性

    6.1.2 操做原子性

6.2 volatile内存语义

    6.2.1 写时,JMM会把对应线程的本地缓存刷新到内存中

        6.2.1.1 写前,加一个storestore

        6.2.1.2 写后,加一个storeload

    6.2.2 读时,JMM会把对应线程会本地缓存置为无效,从新装载内存数据

        6.2.2.1 读后,加一个loadload

        6.2.2.2 读后,加一个loadstore

7 锁的内存语义

7.1 get锁时,JMM会把内存的本地缓存置为无效

7.2 release锁时,JMM会把对应线程的内存刷到内存中

7.3 ReentrantLock的源码实现

    7.3.1 重人锁中,组合了一个Sync的对象,这个对象继承了AbstracQueueSynchronizer对象,acquire与release两个方法,AQS对象经过volatile来实现锁的控制

8 Concurrent包的实现

8.1 套路

    8.1.1 申明共享变量volatile

    8.1.2 用CAS来更新实现线程之间的同步

    8.1.3 陪volatile的读写与CAS的内存语义,实现内存间通讯

9 final内存语义

9.1 写时的重排序规则:JMM禁止编译器把final域的写重排序到构造函数以外,也就是说,在引用对象被其余线程可见以前,final域已经被初始化

    9.1.1 写操做以后,有storestore

9.2 读时的重排序规则:在一个线程中,初次读对象引用与初次读该对象包含的final域,这两个操做,不容许重排序。也就是说,在读这个final域以前,必定得要先读这个对象引用

    9.2.1 读操做以前,有loadload

10 对象逸出

10.1 对象在一个线程中,没有彻底初始化好了以前,就被其余线程引用,这就是说,这个对象在构造函数中“逸出”。

10.2 对象“逸出”,致使final域的值两次读的不同,第一次读的时候,由于引用对象还没完成初始化好,final域也还没执行。第二次读的时候,final域已经执行完了

11 happens-before

11.1 JMM对于编译器,处理器没有啥特别的要求,惟一要求的就是,在不改变程序的运行结果的前提下,你爱怎么玩就怎么玩,我无论

11.2 定义

    11.2.1 一个操做happens-before另一个操做,那么第一个操做的执行结果将对第二个操做可见

相关文章
相关标签/搜索