synchronized同步锁的四种状态
- 无锁: 就是没有加入锁嘛,这个就很好理解了,也就是说此时的目标共享数据没有被任何一个线程占用.
- 偏向锁
- 轻量级锁
- 重量级锁
锁膨胀方向: 无锁–>偏向锁–>轻量级锁–>重量级锁
偏向锁
- 大多数情况下,锁不存在多线程竞争,总是由同一线程多次获得,因此,
为了减少同一线程获取锁的代价
而引入了偏向锁. - 核心思想:
如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word的结构也变为了偏向结构,当该线程再次请求锁
时,无需再做任何同步操作,即获取锁的过程只需要检查Mark Word的锁标记为偏向锁及当前线程Id等于Mark Word的ThreadId即可,这样就省去了大量有关锁申请的操作,即使得线程进入和退出同步块时不需要进行CAS操作来加锁和解锁,
从而也就提高了程序的性能. - 不适合用于锁竞争比较激烈的场合,当偏向锁失败后,会立即升级为轻量级锁.
轻量级锁
轻量级锁是由偏向锁升级而来的,偏向锁运行在只有一个线程申请进入同步块的情况下,当第二个线程加入锁竞争的时候
,偏向锁就会升级为轻量级锁.
- 偏向锁的适用场景: 线程交替执行同步块.
- 如果存在同一时间访问多个线程同一锁的情况,就hi导致轻量级锁膨胀为重量级锁.
轻量级锁的加锁过程:
轻量级锁的解锁过程:
锁的内存语义
当线程释放锁时,java内存模型会把该线程对应的本地内存中的共享变量刷新到主内存中.
而当线程获取到锁时,java内存模型会把该线程对应的本地内存置为无效
,从而使得监视器保护的临界区代码必须从主内存中读取共享变量.
锁的总结