深入理解java虚拟机学习笔记(九)--java内存模型与线程_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 深入理解java虚拟机学习笔记(九)--java内存模型与线程

深入理解java虚拟机学习笔记(九)--java内存模型与线程

 2013/8/25 21:55:09  lg70124752  程序员俱乐部  我要评论(0)
  • 摘要:第十二章java内存模型与线程1、主内存与工作内存java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与java编程中所主的变量略有区别,它包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然就不存在竞争问题。java内存模型规定了所有的变量都存储在主内存中。每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝
  • 标签:笔记 学习 Java 理解 虚拟机 学习笔记 线程 内存
第十二章 java内存模型与线程
1、主内存与工作内存
java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与java编程中所主的变量略有区别,它包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然就不存在竞争问题。java内存模型规定了所有的变量都存储在主内存中。每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。主内存是堆,工作内存是栈,也可以说主内存是硬件内存,工作内存优先存储于寄存器和高速缓存中。
2、对于volatile型变量的特殊规则
volatile变量对所有线程是立即可见的,对volatile变量所有的写操作乾能立刻反应到其它线程中,换句话说,volatile变量在各个线程中是一致的。使用-XX:+PrintAssembly参数输出反汇编来分析并发问题更加严谨些。
volatile屏蔽指令重排序的主义在jdk1.5中才被完全修复,此前的JDK中即使将变量声明为volatile也仍然不能完全避免重排序所导致的问题(主要是volatile变量前后的代码仍然存在重排序问题),这点也是在jdk1.5之前的java中无法安全地使用DCL(双锁检测)来实现单例模式的原因。
3、对于long和double型变量的特殊规则
java内存模型要求lock、unlock、read、load、assign、use、store和write这八个操作都具有原子性,但是对于64位的数据类型(long和double),在模型中特别定义了一条宽松的规定:允许虚拟机将没有被volatile修饰的64位数据的读写操作划分为两次32位的操作来进行,即允许虚拟机实现选择可以不保证64位数据类型的load、store、read和write这四个操作的原子性,这点就是所谓的long和double的非原子性协定。但虚拟机把64位数据的读写操作作为原子操作来对待。
4、等待发生原则
先行发生是java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,"影响"包括修改了内存中共享变量的值、发送了消息、调用了方法等。
Java内存模型下的“天然的”先行发生关系:
A、程序次序规则:在一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作。
B、管和锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。
C、volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个变量的读操作,这里的“后面”同样是指时间上的先后顺序。
D、线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作。
E、线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。
F、线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测到是否有中断发生。
G、对象终结规则:一个对象的初始化完成先行于它的finalize方法的开始。
H、传递性:如果操作A先行发生于操作B,操作B先行发生于操作C,寻就可以得出操作A先行发生操作C的结论。
发表评论
用户名: 匿名