2Java机制的底层实现

java中所使用的并发机制依赖于jvm的实现和cpu的指令

volatile

volatile是轻量级的synchronized,如果这个修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为他不会引起线程上下文的切换和调度

定义:java允许线程访问共享变量,为了确保共享变量能被准确和一致性的更新,线程应该确保通过排他锁单独获得这个变量,如果一个字段被设置成volatile,java线程内存模型确保所以线程看到的这个变量的值是一致的

lock前缀的指令在多核处理器下会做两件事:

1)将当前处理器缓存行的数据写回到系统内存

2)这个写回内存的操作会使在其他cpu里面缓存了该内存地址的数据无效

当使用volatile修饰的变量进行写操作的时候,jvm就会向处理器发送一条lock前缀的指令,通过缓存一致性协议,每个处理器嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读取到缓存里

volatile的两条实现规则

(1)lock前缀指令会引起处理器缓存回写到内存

(2)一个处理器的缓存回写到内存会导致其他的处理器的缓存无效

volatile的优化

LinkedTransferQueue通过追加成64字节的方式提高效率,因为很多处理器的高速缓存行都是64字节,如果不追加空的字节会把头节点和尾节点放到一个缓存行,导致修改的时候缓存锁定,入队和出队不能同时操作而相互锁定

以下两种场景不应该把volatile变量追加到64字节

1)缓存行非64字节的处理器

2)共享变量不会被频繁的写

这种追加字节的方式在java7中不可能生效,因为会淘汰或者重新排序无用的字段,需要使用其他追加字节的方式

 

synchronized

对于普通的同步方法 锁的是当前实例的对象

对于静态的同步方法锁的是当前类的class对象

对于同步代码块 锁的是括号里的对象

jvm基于进入和退出Monitor对象来实现方法同步和代码块同步

synchronized用的锁是存在于java对象头里面的,如果对象是数组类型,则虚拟机用三个字宽存储对象头,如果对象是非数组类型,则使用2个字宽存储对象头,在32位的虚拟机中,一字宽是32bit,即4字节

《Java并发编程的艺术》读书笔记系列二

Mark Word 默认存储对象的hashcode,分代年龄和锁标记位,32位的jvm的 Mark Word 默认存储如下所示

《Java并发编程的艺术》读书笔记系列二 

 Mark Word里面的数据会随着运行而变化,可能有以下四种情况

《Java并发编程的艺术》读书笔记系列二

 64位的存储结构

《Java并发编程的艺术》读书笔记系列二

 

相关文章:

  • 2021-08-08
  • 2021-09-28
  • 2022-01-07
  • 2021-11-02
  • 2021-05-09
  • 2021-09-25
  • 2021-12-04
  • 2021-10-26
猜你喜欢
  • 2021-12-05
  • 2021-12-05
  • 2022-12-23
  • 2021-12-05
  • 2021-07-17
  • 2021-07-29
相关资源
相似解决方案