java并发机制的底层实现原理
所属分类 java
浏览量 1449
Java并发编程的艺术笔记第二章
Java代码 字节码 类加载 jvm 字节码执行 汇编指令 cpu执行
java并发机制依赖 jvm实现 和 cpu指令
synchronized volatile
volatile 保证变量可见性 执行成本更低 不会引起上下文切换
一个字段被声明成 volatile ,java内存模型保证所有线程看到这个变量的值是一致的
cpu高速缓存 L1 L2 L3
内存屏障 memory barriers
缓存行 cache line 高速缓存中可以分配的最小存储单位
volatile 共享变量写操作 lock前缀指令
当前缓存行数据写入内存系统
失效其他cpu缓存数据
cpu缓存一致性协议
总线锁定 缓存行锁定
MESI 修改 独占 共享 失效
伪共享 false share
LinkedTransferQueue
避免头尾节点加载到同一个缓存行 (一般64字节) 使头尾节点修改时不会互相锁定
手工填充 自动填充
@sun.misc.Contended 注解
jvm -XX:-RestrictContended 开启此功能
synchronized 重量级锁
monitorenter 和 monitorexit 指令
Java对象头
Mark world hashCode 分代年龄 锁信息
class metadata address 对象类型数据指针
ArrayLength 数组长度(如果当前对象是数组)
锁升级
无锁状态 偏向锁 轻量级锁 重量级锁
偏向锁 jdk6,7默认开启 竞争激烈的情况下
默认-XX:+UseBiasedLocking=true
-XX:-UseBiasedLocking=false关闭偏向锁
应用程序启动几秒钟之后才激活 -XX:BiasedLockingStartupDelay = 0关闭延迟
偏向锁 在无竞争的情况下把整个同步都消除掉,连CAS操作都省了
轻量级锁 在无竞争的情况下使用CAS操作去消除同步使用的互斥量
偏向锁偏向于第一个获得它的线程。如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要再进行同步。
偏向锁可以提高带有同步但无竞争的程序性能。如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。在具体情形分析下,禁止偏向锁优反而可能提升性能。
轻量级锁 加锁
在代码进入同步块的时候,如果此同步对象没有被锁定(锁标志位为“01”状态),
虚拟机首先将在当前线程栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁记录目前的Mark Word的拷贝(称为Displaced Mark Word)
拷贝mark word的作用 避免在lock与unlock这种底层操作上再加同步。
修改Object mark word轻量级锁指针作用:告诉其他线程,该object monitor已被占用
owner指向object mark word作用:在后续的运行过程中,识别哪个对象被锁住了。
解锁
用CAS操作把对象当前的Mark Word和线程中复制的Displaced Mark Word替换回来,如果替换成功,整个同步过程就完成了。
如果替换失败,说明有其他线程尝试过获取该锁,那就要在释放锁的同时,唤醒被挂起的线程。
CAS实现原子操作的三大问题
ABA问题 一个值从A变成B又变成A,使用CAS检查时以为没有变化,但实际上却变化了。解决思路是使用版本号。
循环时长长,开销大。
只能保证一个共享变量的原子操作。(Java1.5以后,JDK提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里来进行CAS操作)
上一篇
下一篇
找出最耗CPU的java线程和代码
线上问题排查常用命令
Lock和synchronized的区别
域名查询命令
java线程状态
互联网新老词汇对照表