在Java中,Synchronized关键字可以用于实现对代码块或方法的同步,保证多线程之间的互斥访问。在Synchronized中,锁的升级过程包括偏向锁、轻量级锁和重量级锁,具体过程如下:
- 偏向锁(Biased Locking):
- 偏向锁是一种针对单线程的优化手段,如果一个线程获得了偏向锁,那么在未发生竞争的情况下,该线程再次进入同步块时无需进行同步操作,可以直接进入,从而减少了获取锁的成本。
- 当一个线程第一次进入同步块时,锁会升级为偏向锁,并且该线程的线程ID会被记录在锁对象的头部。当其他线程尝试进入同步块时,会发现有线程已经占用了偏向锁,此时会尝试撤销偏向锁,将锁升级为轻量级锁。
- 轻量级锁(Lightweight Locking):
- 如果存在多个线程竞争同一个偏向锁,偏向锁就会失效,此时锁会升级为轻量级锁。
- 在轻量级锁中,锁对象的头部会存储指向拥有锁的线程的指针,同时使用CAS操作尝试将该指针替换成当前线程的指针。如果CAS成功,表示当前线程成功获取了锁,可以进入同步块;如果CAS失败,表示有其他线程竞争锁,则会进入自旋,尝试获取锁。
- 重量级锁(Heavyweight Locking):
- 如果在轻量级锁的自旋阶段仍然无法获得锁,锁就会升级为重量级锁。重量级锁会使得持有锁的线程进入阻塞状态,释放CPU资源。
- 重量级锁的实现通常会涉及到操作系统的底层调用,如pthread_mutex_lock()等,这样的锁操作涉及到用户态和内核态的切换,开销较大。
锁的升级过程是从偏向锁到轻量级锁,再到重量级锁的一个演变过程。这个过程是为了在不同的并发场景下,尽量减少锁的竞争和升级的开销,提高程序的性能。