轻量级锁
2017-12-11 本文已影响0人
水欣
- 轻量级锁加锁
线程在执行同步块之前,JVM 会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的 Mark Word 复制到锁记录中,官方称为 Displaced Mark Word。然后线程尝试使用 CAS 将对象头中的 Mark Word 替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。 -
轻量级锁解锁
轻量级解锁时,会使用原子的 CAS 操作将 Displaced Mark Word 替换回对象头,如果成功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。下乳是两个线程同时竞争锁,导致锁膨胀的流程图。
2.png
因为自旋会消耗 CPU,为了避免无用的自旋(比如获得锁的线程被阻塞住了),一旦线程升级成重量级锁,就不会再恢复到轻量级锁状态。当锁处于这个状态下,其他线程尝试获取锁,都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程,被唤醒的线程会进行新一轮的夺锁之争。
- 锁的优缺点对比
锁 | 优点 | 缺点 | 使用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 | 如果线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了线程的相应速度 | 如果始终得不到锁竞争的线程,使用自旋会消耗CPU | 追求相应时间,同步块执行的速度非常快 |
重量级锁 | 线程竞争不使用自旋,不会消耗CPU | 线程阻塞,响应时间缓慢 | 追求吞吐量,同步块执行时间较长。 |