Synchronized原理:Java 中的每个对象都有一个对象头,其中包含锁信息(Mark Word)。这个锁标志位可以记录对象的锁定状态、线程锁的HashCode、偏向锁和轻量级锁等信息。
1.偏向锁
当一个线程第一次获取对象锁时,会将对象头中的锁标志位设置为偏向锁状态,并记录获取锁的线程 ID。
如果同一个线程再次获取锁,偏向锁会直接让其获取,无需进行同步操作。
如果其他线程尝试获取同一个锁,偏向锁会升级为轻量级锁。
2.轻量级锁
使用 CAS 操作尝试获取锁。如果 CAS 操作成功,线程获取锁;如果失败,线程会不断重试(自旋)。
如果两个线程同时竞争同一个轻量级锁,轻量级锁会升级为重量级锁。
3.重量级锁
使用操作系统的互斥量(mutex)来实现锁的获取和释放。
重量级锁会导致线程阻塞和唤醒,开销较大。
Lock原理:Lock 是 Java 中的一种显式同步机制,提供比 synchronized 更加灵活的同步功能。Lock 的底层实现主要依赖于 AQS(AbstractQueuedSynchronizer)。
1.AQS(AbstractQueuedSynchronizer)
AQS 是一个用于构建锁和同步器的框架,它使用一个 FIFO(先进先出)队列来管理线程的获取和释放同步状态。
同步状态管理:AQS 使用一个 FIFO 队列来记录获取同步状态的线程。
获取同步状态:线程通过 CAS 操作尝试获取同步状态,如果获取失败,线程会被加入队列并阻塞。
释放同步状态:线程释放同步状态后,AQS 会唤醒队列中下一个线程。
2.ReentrantLock
ReentrantLock 是 Lock 接口的一个实现类,它支持可重入锁,并提供公平锁和非公平锁两种模式。
公平锁:线程按照请求的顺序获取锁。
非公平锁:线程可能在队列中插队,获取锁的顺序不一定按照请求的顺序。