Java HotSpot™ 虚拟机同步机制的实现

Java HotSpot™ 虚拟机同步机制的实现

Tags
Java
Lock
Published
November 1, 2017
Author
Joybean

Mark Word

谈JVM的同步机制,不得不先了解一下Java对象头中的Mark Word,JVM同步的实现离不开这个数据结构。
存储内容
标记
状态
hash、对象分代年龄
01
无锁
指向(虚拟机栈中)锁记录地址的指针
00
轻量级锁
指向操作系统重量级锁的指针
10
重量级锁
11
GC标记
偏向线程ID、对象分代年龄
01
偏向/可偏向锁

锁的类型

重量级锁(heavy-weight locking)

操作系统级别的锁机制,包括互斥(mutex)对象和条件变量(condition variables)

轻量级锁(light-weight locking)

所有现代JVM都引入了经量级锁:
  • 避免将每个对象关联操作系统的重量级锁
  • 当不存在锁竞争时,使用原子操作来进入退出同步块
  • 如果发生锁竞争,回退到操作系统的重量级锁
使用轻量级锁会提高效率,因为大部分锁都不存在竞争。

具体实现

notion image
上图描述了标准的加锁过程:
  1. 开始对象处于未锁定状态。
  1. 当在对象上进行同步时,mark word被拷贝到当前线程栈帧上的锁记录(lock record,用于追踪被当前线程锁定的对象)中,它被称之为displaced mark。
  1. 线程使用原子的CAS(Compare-and-swap)指令尝试将mark word的指针指向帧栈上的锁记录。
  1. 若CAS成功,则该线程获得锁。
  1. 若CAS失败,则轻量级锁膨胀为重量级锁以管理等待线程。
由于在多处理器上执行原子的CAS操作代价是昂贵的,大多数锁不仅不存在竞争,它们还通常由同一个线程重复加锁/解锁。为了解决这些问题,引入了偏向锁(Biased Locking),只有第一次获取锁时,使用CAS操作将线程ID置于对象头的mark word中 。这个对象会偏向于第一次获取锁的线程,之后该线程锁定和解锁对象不需要任何原子操作或mark word的更新。若另外的一个线程锁定了该对象,则取消偏向。

总结

轻量级锁在使用操作系统重量级锁之前,首先进行CAS操作以减少系统开销,因为大部分锁都是无竞争的。
偏向锁的目的是无竞争的时候连CAS操作都不需要,直接使用偏向线程。

参考