zoukankan      html  css  js  c++  java
  • 02-java内存模型:解决并发编程的可见性、有序性问题

    并发编程的两个问题:缓存导致的不可见,编译优化导致的有序性问题

    解决:禁用缓存,禁用编译优化。但是总不能所有程序都禁用吧,这样程序的性能就堪忧了。

    Java内存模型:按需禁用缓存,禁用编译优化。

    从本质上来讲,Java内存模型规范了JVM如何提供按需禁用缓存和编译优化的方法。具体来说,这些方法包括volatile、synchronized、和final三个关键字,以及七项happens-before规则。

    一、volatile

      它修饰的变量,告诉编译器,对这个变量的读写,不能使用cpu缓存,必须从内存中读取或写入。

    二、synchronized

      管程,在Java中指的就是synchronized。在进入代码块之前,会自动加锁,在代码块执行完会自动释放锁。

    三、final

      它修饰的变量,告诉编译器:这个变量生而不变,可以可劲儿优化。

    happens-before规则:

    1、程序的顺序性规则

    指在一个线程中,按照程序顺序,前面的操作happens-before于后续的任意操作

    2、volatile变量规则

    指 对一个volatile变量的写操作,happens-before于后续对这个volatile变量的读操作。

    3、传递性

    如果A  happens-before于B,B happens-before于 C,那么A happens-before 于 C。

    4、管程中锁的规则

    即synchronized代码块happens-before于后续进入该代码块以及后续的所有操作。

    5、线程start()规则

    线程A启动子线程B,那么子线程B能够看到线程A在启动线程B前的操作。

    6、线程join()规则

    这条是关于线程等待的。在线程A中调用线程B的join()并成功返回,那么线程B中的任意操作happens-before于该join()操作的返回。

    7、线程终止规则

    (1).线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。
    (2).线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测到是否有中断发生。

    四、Java内存模型底层怎么实现的?

    主要是通过内存屏障(memory barrier)禁止重排序的,即时编译器根据具体的底层体系架构,将这些内存屏障替换成具体的 CPU 指令。对于编译器而言,内存屏障将限制它所能做的重排序优化。而对于处理器而言,内存屏障将会导致缓存的刷新操作。比如,对于volatile,编译器将在volatile字段的读写操作前后各插入一些内存屏障。

  • 相关阅读:
    Notes about "Exploring Expect"
    Reuse Sonar Checkstyle Violation Report for Custom Data Analysis
    Eclipse带参数调试的方法
    MIT Scheme Development on Ubuntu
    Manage Historical Snapshots in Sonarqube
    U盘自动弹出脚本
    hg的常用配置
    Java程序员的推荐阅读书籍
    使用shared memory 计算矩阵乘法 (其实并没有加速多少)
    CUDA 笔记
  • 原文地址:https://www.cnblogs.com/bbsh/p/11657669.html
Copyright © 2011-2022 走看看