2004-10-25
第八章线程和锁
这章描述的是非常底层的jvm运作的时候的概念上的部分模型,与前部分的编译不属于一个层次。
本章提到的变量概念是指类实例,类变量,和类数组。而参数和局部变量并不强行要求到这个变量概念之中。
8。1术语和框架
jvm中有主寄存器,当一个线程被启动时,会创建自己的工作寄存器,当线程运行,会对主寄存器中的数据进行拷贝,存入自己的工作寄存器中。
主寄存器包含每个变量的主拷贝。
主寄存器也包含锁,每个对象有个与其相关的锁。线程可以竞争获得一个锁。
相关术语:
use,assign,load,store,lock,unlock为线程可以执行的动作。
read,write,lock,unlock为主存储器子系统可以执行的动作。
use,assign是线程执行引擎与工作存储之间的紧密耦合交互作用。
lock,unlock是线程执行引擎与主存储之间的紧密耦合交互作用。
主存储与工作存储之间却是松散耦合的。
分别对应的动作就是:load,store和lock,unlock
注意有三个实体在协同工作:主存储器,工作存储器,线程运行引擎
8。2执行顺序和一致性。
1。同线程执行动作排序
2、主存储执行的、对同一变量的动作排序
3、主存储执行的、对同一锁的动作排序
4、不允许一个动作跟在其自身后面。
第4点特殊说明:虽然看起来无关紧要,但必须显式说明,以保证完整性。因为这种危险确实存在。
线程的动作和主存储的动作间的约束:
1、每个lock和unlock动作必须由一些线程和主存储共同执行。
2、每个load动作,唯一的与一个write动作配对,这样write动作跟在store动作后。
8。3有关变量的规则
线程T对变量V的操作约束:
1、T执行过程中只有需要相应使用V时才调用use,或者assign动作。
2、T执行的assign动作必须插入到T对V的load或者store和后继的由T执行的对V的store之间。(保证主存储内值的正确,同时保证assign动作之前工作存储内存在V)
3、在T对V执行use和store之前,必须执行assign或load操作(保证工作存储器中有V,并且已经初始化)
4、在V创建后,每个T在use或store之前,必须执行assign或load操作。
对于第4点:volatile(易变)变量有更严格的约束
由主存储器执行的read和right操作的约束:
1、T对V的load,必须先有对应的read
2、T对V的store,必须后继对应的write
3、动作A,B是T对V的load或store动作,P,Q为对应的read或write,如果A优先于B,则P必须有些于Q
8.4Double和long变量的非原子处理
由于32位机器的效率问题,有些jvm实现对double和long这种64位值操作是非原子的,导致一些同步问题(如程序员总是需要显式指定同步于对double和long上的操作),其实这只是一种软件设计对硬件的妥协而已。
8。5有关锁的规则
线程为T,锁为L,T执行的关于L的操作约束如下:
1、T对L的lock操作,必须对于每个不是T的线程S,S对L的unlock操作数等于之前的S对L的lock操作数
2、T对L的unlock操作,必须要求先前T对L的unlock操作数,小于先前T对L的lock操作数(不解不拥有的锁)
8。6有关锁和变量交互作用的规则
线程T,锁L,变量V,T执行的关于L和V的操作约束如下:
1、在t对V的assign和随后的unlock之间,必须插入store操作。对应于该store的write操作必须先于unlock操作(保证L对于V的有效性)。
2、在lock和随后执行的use或store之间,必须插入assign或load操作。
8。7有关volatile(易变)变量的规则
线程T,易变变量V和W
1、load和use操作必须成对出现,紧挨在一起,并且load操作在前
2、assign和store操作必须成对出现,紧挨在一起,并且assign操作在前
3、A、B为T对V的use或assign,F、G为对应的load或store,P、Q为对应的read或write,如果A先于B,则P必须优先于Q。
8。8先见存储操作
如果变量没有声明为violate,则store操作可以提前于assign,store操作将将要赋给V的值替代V实际的值进行store操作,只要满足:
1、如果发生store,必然发生assign。
2、重定位的store和assign间未插入锁定操作。
3、重定位的store和assign间未插入对V的load
4、重定位的store和assign间未插入其他对V的store
5、store操作将assign操作要放到线程T的Z作为存储器中的值传到主存储器。
8。9讨论
8。10可能的交换
一个关于同步和锁的小例子。
8。11范例:无序写
另一个例子
8。12线程
线程由Thread和ThreadGroup类创建并管理。创建Thread对象就创建一个线程,而且是创建线程的唯一方式。当线程被创建时,它还不是活跃的,当其start方法被调用时,开始运行。
8。13锁和同步
每个对象都有与其关联的锁。
当synchronized方法被调用时,它自动执行锁定操作;如果该方法是实例方法,它锁定同实例相关联的锁,如果方法是static的,它锁定同Class对象相关联的锁
8。13等待集和通知
每个对象除了相关的锁外,还有相关的等待集,即一组线程,首次创建的对象,等待集为空。
讲述了wait,notify,notifyall几个方法,wait方法往等待集中增加内容,而notify或notifyall方法从等待集中删除内容。
但不能完全读懂内容,可细研究。
第九章优化
本章描述jvm中Sun版本中实现的优化。
在此优化中,编译的jvm代码在运行期修改,利用运行期获得的信息,做比源指令更少的工作,以获得更好的性能。
9。1通过重写动态链接
对重写的指令,指令的每个实例在其第一次执行时被替换为_quick伪指令,该指令实例随后执行的总是_quick变体。
其余是对_quick伪指令的描述,可用于查阅,因为这是Sun的jdk在运行的时候的真正指令状态。
第十章 操作码的操作码助记符
这章主要是个附录的功能,可供查阅。
×××××××××××××××××××××××××××××××××××
在延期了将近一个月了之后,终于算是看过了一遍这本书,虽然有很多没有看的非常明白的地方,但是比我预期的效果要好了许多了,进一步的细致研究可以安排在后面。