《深入理解java虚拟机:jvm高级特性与最佳实践》笔记——Java内存模型

a) 主内存和工作内存:除了局部变量和方法参数(线程私有),所有的变量都存在主内存中,每条线程都有自己的工作内存,保存该线程用到的主内存副本,线程操作只在工作内存中。

b) 内存间交互操作(操作具有原子性):变量在主内存和工作内存之间的同步实现细节。
简单来说就是,lock,ulock是作用于主内存变量的,是线程锁操作的基础,read和load是线程同步主内存的过程,先读(read)主内存变量,然后在写(load)到线程的工作内存中,store和write是线程同步到主内存的过程,先读(store)工作内存变量,然后更新到(write)主内存中。Use是执行器拿工作内存变量的过程,assign是执行器更新工作内存变量的过程。
主要规则是,各个过程中的操作不能单独存在,变量必须在主内存中诞生,新变量use前必须先load,assign后必须write到主内存(但不一定立即),lock,ulock必须成对存在,并且线程对应。Unlock必须将更新了的工作内存变量write回主内存。

具体解释如下:
i. Lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
ii. Unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来。
iii. Read(读取):作用于主内存的变量,把一个变量的值从主内存传输到线程的工作内存,供load动作使用。
iv. Load(载入):作用于工作内存的变量,把read操作从主内存中得到的变量值放入工作内存的变量副本中
v. Use(使用):作用于工作内存,把工作内存中一个变量的值传递给执行引擎。
vi. Assign(赋值):作用于工作内存,把从执行引擎接到的值赋值给工作内存变量。
vii. Store(存储):作用于工作内存的变量,把工作内存中一个变量的值传递给主内存,供write操作使用
viii. Write(写入):作用于主内存的变量,把store操作得到的值,放入主内存的变量中。
c) 操作规则:
i. 不允许read和load、store和write操作之一单独出现。
ii. 不允许线程丢弃它最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步到主内存中。
iii. 不允许一个线程无原因的(未发生assign操作)把数据从线程工作内存同步到主内存中
iv. 一个新的变量只能在主内存中诞生,不允许工作内存直接使用(use或store)未被初始化(load或assign)的变量。
v. 一个变量同一时刻只允许一个线程lock,可以多次lock,但unlock数同样多,才能被解锁。
vi. 如果一个变量被lock,则清空工作内存中该变量的值,执行引擎使用前,需要重新load或者assign操作。
vii. 不允许unlock未被lock的变量,也不允许unlock其他线程的lock。
viii. 对一个变量unlock前,必须先执行store和write操作,同步回主内存。
d) Volatile型变量的特殊规则:
主要有两个,一个是,每次use时先load,assign之后立即store,中间不允许有其他操作,也就是我们平时说的线程可见性。另外一个是保证各个线程之间指令顺序不被打乱,即不允许指令重排。这并不能保证线程安全(因为线程提交之时,并未确定原值是否被修改:比如,A,B线程同时拿到变量a=10,在两个线程同时自增1,然后先后写入主线程都为11,最终主线程为a=11,而非我们期待的12),具体如下:
i. 保证变量对所有线程的可见性。值更改,会被其他线程立即得知。

  1. 运算结果不依赖变量的当前值,或能够保证只有单一线程修改变量值。
  2. 变量不需要与其他的状态变量共同参与不变约束。
    ii. 禁止指令重排优化(保证在该方法执行过程中所依赖的赋值结果的地方能够获取正确结果,不保证变量赋值操作顺序与程序代码执行顺序一致):通过插入内存屏障指令来保证处理器不发生乱序执行。
    iii. 特殊规则:
  3. 当前线程对变量执行动作时,use必须在同一变量load(和read)操作之后,成对连续,并且中间不允许有其他操作加入,保证能看到其他线程对该变量的修改。
  4. 当前线程对变量执行动作时,store(和write)必须在同一变量assign操作之后,成对连续出现,并且中间不允许有其他操作加入,保证能其他线程能看到该线程对该变量的修改。
  5. 线程对变量A的use或assign动作先于对变量B的use或assign,那么对相关联动作A的read或write也一定要先于B的read或write,保证代码执行顺序与程序顺序相同,不被指令重排优化。
    e) 对long和double型变量的特殊规则:非原子性协定(允许虚拟机对没有volatile修饰的64位数据的读写分两次32位的操作来执行,即不保证64位数据类型的load、store、read和write的原子性)。但虚拟机实现推荐,也会实现为原子性操作。
    f) 模型特征:
    i. 原子性:基本类型都是具有原子性的,java内存开放的lock和unlock操作用来保证原子性,另外提供更高层次的字节码操作monitorenter和monitorexit来隐式使用,即synchronized关键字。
    ii. 可见性:一个线程修改共享变量值,其他线程能够立即得知。除了Volatile关键字(读取、修改都立即操作主内存)外,还有synchronized(对一个变量执行unlock之前,必须将其同步到主内存中)和final(被其修饰的变量在构造器中初始化完成,并且没有this引用传递出去【this引用逃逸】)。
    iii. 有序性:线程内有序串行表现,线程外无序。提供了volatile和synchronized来保证有序性。、
    g) 先行发生原则:操作A先行发生于操作B,那么操作A产生的影响能被操作B观察到。
    i. 程序次序原则:一个线程内,书写在前面的操作先行发生于书写在后面的操作,为控制流顺序。
    ii. 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。时间顺序
    iii. Volatile变量规则:对同一个volatile变量的写操作先行发生于后面对这个变量的读操作。时间顺序
    iv. 线程启动规则:线程对象的start方法先行发生于此线程的每一个动作
    v. 线程终止规则:线程中所有操作都先行于该线程的终止检测。
    vi. 线程中断规则:对线程interrupt方法调用先行发生于被中断线程的代码检测到中断事件的发生
    vii. 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行于它的finalize方法的开始
    viii. 传递性:如果A先行发生于B,B先行发生于C,那么A先行发生于C
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值