zoukankan      html  css  js  c++  java
  • 了解Java内存模型,看完这一篇就够了

    前言(此文草稿是年前写的,但由于杂事甚多一直未完善好。清明假无事,便收收尾发布了)

        年关将近,个人工作学习怠惰了不少。两年前刚做开发的时候,信心满满想看看一个人通过自己的努力,最终能达到一个什么样的高度。而近半年

    深陷生活的泥淖中,却有点被压迫住的感觉。个人成长、家庭、父母、朋友、身边的人,无不或多或少的影响着我的心境。很多时候还是要多反思一些,

    通过思考让自己重拾信心,继续打满鸡血的前行。中国当前的大环境纵然有波折,但总体是向上的,互联网行业也是出于深度改造各行各业的状态,而且

    个人对计算机对编程很有热情,一息理想尚存,想要自己的人生有所不同。所以不管怎样,这条路还要好好的走下去。这个把月多学习吧,为节后的

    机会最好准备。

    正文

        闲话少叙,下面开始正题。首先要明确内存模型指什么。书中的定义是:在特定的操作协议下,对特定内存和高速缓存进行读写访问的过程抽象

    可以知道,内存模型就是来规定如何对内存/缓存进行读写操作的。所以Java内存模型,就是用来定义程序对java内存的的访问规则。进一步说, java内存

    模型就是定义程序中变量(静态变量、数组对象元素等,不包括局部变量、方法参数)的访问规则。

    Java内存模型的规定:

    1、所有变量存储在主内存中;

    2、每个线程都有自己的工作内存,且对变量的操作都是在工作内存中进行;

    3、不同线程之间无法直接访问彼此工作内存中的变量,要想访问只能通过主内存来传递。

    java的线程、工作内存、主内存关系如下图所示:

    具体变量从主内存到工作内存,以及从工作内存转回主内存的实现细节,由下面八个原子性的操作完成:

    lock:作用于主内存变量,将该变量标识为一个线程独占的状态

    unlock:作用于主内存变量,将独占状态释放

    read:作用于主内存变量,将值拷贝到工作内存中

    load:作用于工作内存中的变量,将值放到工作内存中的变量副本中

    use:作用于工作内存中的变量,将值传给执行引擎

    asign:作用于工作内存中的变量,将执行引擎中的值赋给工作内存中的变量

    store:作用于工作内存中的变量,将值传给主内存

    write:作用于主内存中的变量,将工作内存中返回的值放到主内存变量中

    同时还对上述八个操作进行了一些细节的要求,比如read/load、store/write必须成对出现,未执行过lock的变量不能执行unlock操作等。

    划重点,此处面试常遇到的问题就是对于volatile关键字的解读。

    volatile关键字

    此关键字修饰的变量具有两种效果:1、保证线程间的可见性;2、阻止指令重排序

    对于1的实现,它保证load与use必须相邻调用,即要use这个变量,必定先执行read/load,这样每次都能获取到最新的变量值;它又保证asign与store

    必须相邻调用,即在工作内存中将该变量改了之后,必定会先同步到主内存中。这样,volatile关键字实现了可见性。至于阻止指令重排序,还是移步

    《深入理解java虚拟机》一书吧,贫道水平有限,就不在这里说了。

    从另一个角度来分析,Java内存模型是围绕着在并发过程中如何处理原子性、可见性、有序性来建立的。

    原子性:八个原子性操作,以及synchronized(lock/unlock未直接开放给用户,synchronized通过monitorenter跟monitorexit指令调用的lock/unlock操作)

    可见性:volatile、synchronized、final这三个关键字均通过不同方式实现了可见性

    有序性:volatile、synchronized  这两个关键字保证有序性,同时还有先行发生(happens-before)原则来保证隐含的默认有序性

    下面说说happens-before先行发生原则,先行发生原则用通俗语言表述就是:如果操作A在操作B之前发生,那么A产生的影响B同样能观测到。那么问题来

    了,先行发生原则都有哪些呢?同样有八条,如下:

    程序次序规则:同一个线程中按照代码的顺序依次执行

    管程锁定规则:对于同一个锁,unlock先行发生于后面的lock,即unlock了才会lock

    volatile变量规则:对一个volatile变量的写操作先行发生于后面对该变量的读操作,即写完了才会读

    线程启动规则:一个线程的start()方法先行发生于此线程的任何一个动作

    线程终止规则:一个线程的所有动作先行发生于该线程的终止检测

    线程中断规则:对一个线程interrupt()方法的调用先行发生于线程的中断检测Thread.interrpted()

    对象终结规则:对象的初始化完成先行发生于finalize()方法

    传递性:顾名思义,A先行发生于B,B先行发生于C,则A一定先行发生于C

    总结

        java内存模型基本就这些内容,如果都掌握了的话,非一线互联网公司基本都能应对自如了(因为一线互联网公司贫道本人也没进去><)。

  • 相关阅读:
    win7下的vxworks总结
    ubuntu 无法获得锁 /var/lib/dpkg/lock
    项目中用到了的一些批处理文件
    win7下安装 WINDRIVER.TORNADO.V2.2.FOR.ARM
    使用opencv统计视频库的总时长
    January 05th, 2018 Week 01st Friday
    January 04th, 2018 Week 01st Thursday
    January 03rd, 2018 Week 01st Wednesday
    January 02nd, 2018 Week 01st Tuesday
    January 01st, 2018 Week 01st Monday
  • 原文地址:https://www.cnblogs.com/zzq6032010/p/10328399.html
Copyright © 2011-2022 走看看