《深入理解Java虚拟机》笔记之第12章 Java内存模型与线程

1Java内存模型

       Java包括内存模型规定了所有的变量(这里的变量与java编程中的变量略有区别,它包括了实例字段、静态字段和构成数据对象的元素,但不包括局部变量和方法参数,因为后者是线程私有的,不会被共享)都存储在主内存中,此外,每个线程还有自己的工作内存。

线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝。线程对变量的所有操作都在工作内存中进行,不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递都需要主内存来传递。线程、主内存、工作内存三者的交互关系如下图所示。

《《深入理解Java虚拟机》笔记之第12章 Java内存模型与线程》
 

      

主内存、工作内存的划分与java堆、栈、方法区的划分不是同一个层次的内存划分。粗略来看,主内存主要对应于java堆中对象的实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。

 

2、原子性、可见性和有序性

(1)原子性(Atomicity)Java内存模型要求lockunlockreadloadassignusestorewrite这八个操作具有原子性。因此可以认为基本数据类型的读写是具有原子性的(longdouble的非原子性协定除外,但事实上这种情况非常罕见。因为尽管Java内存模型虽然允许虚拟机不把longdouble变量的读写实现成原子操作,但“强烈建议”虚拟机实现为具有原子性的操作。目前各种商业机也几乎是这样做的)。

synchronized则从更大范围上通过lockunlock操作来保证原子性。

如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎全用这个变量前,需要重新执行load或者assgin操作初始化变量的值;

对一个变量执行unlock操作前,必须先把此变量同步回主内存中(执行storewrite操作)。

      (2)可见性(Visibiliy)volatilesynchronizedfinal可以保证可见性。(final有一种例外,即初始化时,构造器把”this”的引用传递出去,造成this引用逃逸,其他线程有可能访问到“初始化了一半”的对象)。

      (3)有序性(Ordering):本线程内观察,所有操作都是有序的;在一个线程中观察另一个线程,所以操作都是无序的(“指令重排序”和“工作内存与主内存同步延迟”)。

       可以通过volatile(禁止重排序)和synchronized(同步块只能串行操作)来保证有序性。

 

3、先行发生原则

      Java语言无须任何同步手段保障就能成立的先行发生规则如下:

1)程序次序规则(Program Order Rule):一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作;

     2)管程锁定规则(Monitor Lock Rule):一个unlock操作先行发生于后面对同一个锁的lock操作;

     3volatile变量规则(Volatile Variable Rule):volatile的写操作先行发生于后面对这个变量的读操作;

     4)线程启动规则(Thread Start Rule):Thread对象的start()方法先行发生于此线程的每一个动作;

     5)线程终止规则(Thread Termination Rule):线程中的所有操作都先行发生于此线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行;

     6)线程中断规则(Thread Interrupt Rule):对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupt()方法检测到是否有中断发生;

     7)对象终结规则(Finalizer Rule):一个对象的初始化完成(构造函数执行结束)先行发生于它的finzlize()方法的开始;

     8)传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。

        时间上的先后顺序与先行发生原则之间基本没有太大的关系:一个操作“时间上的先发生”不代表这个操作是“先行发生”(如两个线程先后gettersetter一个属性值);一个操作“先行发生”也不代表这个操作“时间上先发生”(如两条不相关的赋值语句,不知道处理器会先执行那一条)。

 

4、线程优先级并不是太靠谱

原因在于:Java的线程是被映射到系统的原生线程上来实现的,所以线程调度最终还是由操作系统决定。换言之,优先级在不同的平台上可能不一样。如Java语言设置了10个优先级,Solaris中有2147483628(231次方)种优先级,但windows就只有7种(必然会预见现java中优先级不一样的,在windows中会一样)。

此外,优先级也可能被系统自行改变,如windows中的优先级推进器”(Priority Boosting)

 

 

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/iteye_7011/article/details/82524166
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞