美文网首页程序员
Java内存模型(续)

Java内存模型(续)

作者: sugaryaruan | 来源:发表于2016-07-10 14:17 被阅读215次

    最近看到一个专题讲解Java内存模型的,感觉干货满满,现记录如下:

    深入理解Java内存模型(一)——顺序

    深入理解Java内存模型(二)——重排序

    深入理解Java内存模型(三)——顺序一致性

    深入理解Java内存模型(四)——volatile

    深入理解Java内存模型(五)——锁

    深入理解Java内存模型(六)——final

    深入理解Java内存模型(七)——总结

    在我之前的一篇博客 Java内存模型 中,对Java的内存做了一番简单的梳理。通过上述专题的阅读和学习,又有了新的认识和思考。

    关于Java的锁

    当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。这一操作和volatile变量的写操作相同功效

    当线程获取锁时,JMM会把该线程对应的本地内存置为无效,这一操作和volatile变量的读操作相同共享

    也即是文中总结的:锁释放与volatile写有相同的内存语义;锁获取与volatile读有相同的内存语义。

    由此也自然联想到,Java锁的内部实现,其实就是通过volatile来实现的。

    这里还涉及到公平锁,和非公平锁,这两者的区别是:

    公平的锁上,线程按照他们发出请求的顺序获取锁.当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。

    关于Java的final

    对于final域,编译器和处理器要遵守两个重排序规则:

    1. 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
    2. 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

    在构造函数内部,不能让这个被构造对象的引用为其他线程可见,也就是对象引用不能在构造函数中“逸出”。

    逸出还涉及到安全发布的概念(这里略去不细说)

    重排序

    重排序分为两大类:

    1. 编译器重排序
    2. 处理器重排序,该排序可细化为指令级并行的重排序和内存系统的重排序

    内存屏障:对于处理器重排序,JMM的处理器重排序规则会要求java编译器在生成指令序列时,插入特定类型的内存屏障(memory barriers,intel称之为memory fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序(不是所有的处理器重排序都要禁止)

    内存模型

    越是追求性能的处理器,内存模型设计的会越弱,模型由强变弱依次为:

    1. 顺序一致性内存模型

    2. JMM

    3. 处理器内存模型

    happens-before:如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间.


    参考资料

    Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制

    相关文章

      网友评论

        本文标题:Java内存模型(续)

        本文链接:https://www.haomeiwen.com/subject/qnsdjttx.html