在Java中,synchronized
关键字是用于实现线程同步的一种机制,它提供了偏向锁、轻量级锁和重量级锁三种锁状态来优化同步性能。以下是这三种锁的原理和使用方法的详细解释:
一、偏向锁(Biased Locking)
-
原理
- 偏向锁的目的是为了优化只有一个线程访问同步块的场景。在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得。偏向锁会在对象头(Mark Word)中存储锁偏向的线程ID,以后该线程进入和退出同步块时只需要检查是否为偏向锁、锁标志位以及ThreadID即可。
- 偏向锁的线程会检查锁对象的Mark Word中是否存放着自己的线程ID。如果存放的是当前线程的ID,表示偏向锁现在就是偏向当前线程的,无需再尝试获得锁,可以直接进入同步块。如果不是当前线程的ID,则会发生竞争,当前线程会尝试通过CAS(Compare-And-Swap)操作更新锁对象Mark Word中的线程ID。
- 如果更新成功,锁重新偏向为当前线程,锁仍然为偏向锁。如果更新失败,表示之前的线程还在持有锁,那么当前线程会进行CAS自旋操作,当达到一定次数后还没成功,则会发生偏向锁到轻量级锁的升级。
-
使用方法
- 偏向锁是Java虚拟机(JVM)在JDK 1.6及以后版本中默认启用的优化机制,无需开发者显式使用。但可以通过JVM参数
-XX:+UseBiasedLocking
来显式启用或-XX:-UseBiasedLocking
来禁用偏向锁。 - 偏向锁在应用程序启动几秒钟(默认延迟4秒)之后才会激活,可以使用
-XX:BiasedLockingStartupDelay=0
参数关闭延迟,让其在程序启动时立刻启动。
- 偏向锁是Java虚拟机(JVM)在JDK 1.6及以后版本中默认启用的优化机制,无需开发者显式使用。但可以通过JVM参数
二、轻量级锁
-
原理
- 轻量级锁是为了减少线程从内核态和用户态的切换而设计的,适用于多线程竞争不激烈的情况。它通过CAS机制来竞争锁,避免了重量级锁产生的性能消耗。
- 当一个线程尝试获取轻量级锁时,JVM会首先在抢锁线程的栈帧中建立一个锁记录(Lock Record),用于存储对象目前的Mark Word拷贝。然后,抢锁线程通过自旋操作尝试将内置锁对象头的Mark Word的锁记录指针(ptr_lock_record)更新为抢锁线程中锁记录的地址。如果更新成功&