什么叫获取到了锁
在Java中,“获取到了锁”这一概念并非抽象说法,而是通过底层数据结构和线程状态的显式管理实现的。具体判断逻辑因锁类型不同而有所差异,以下是核心机制解析:
一、synchronized锁的获取判断
1. 对象头与Monitor机制
- 底层实现:每个Java对象头中的Mark Word字段存储了锁状态信息(如偏向锁、轻量级锁、重量级锁标志位)。
- 获取锁的判断逻辑:
- 无锁状态:Mark Word标志位为
01,线程通过CAS操作尝试将锁标志位修改为偏向锁或轻量级锁。 - 偏向锁:Mark Word中记录线程ID,若当前线程ID匹配则直接获取锁(无需竞争)。
- 轻量级锁:通过CAS操作将对象头替换为指向线程栈中锁记录的指针,成功则获取锁。
- 重量级锁:依赖操作系统的互斥量(Mutex),线程需进入Monitor的Entry List队列等待唤醒。
- 无锁状态:Mark Word标志位为
2. Monitor计数器
- 计数器(count):记录线程重入次数。
- 线程首次获取锁时,计数器置1;每次重入计数器+1,释放时计数器-1,归零时彻底释放锁。
二、ReentrantLock锁的获取判断
1. AQS(AbstractQueuedSynchronizer)机制
- state变量:核心状态标识,0表示未锁定,≥1表示锁被占用(可重入次数)。
- 线程通过CAS操作将state从0改为1,成功则获取锁;失败则加入CLH队列等待。
- exclusiveOwnerThread:记录当前持有锁的线程,用于实现可重入性。
2. 公平性与非公平性
- 非公平锁:新线程直接尝试CAS抢锁,无需排队。
- 公平锁:检查CLH队列是否有等待线程,若有则排队。
三、锁获取的通用判断逻辑
1. 硬件级原子操作(CAS)
- 所有锁的获取最终依赖CPU的CAS指令(Compare-And-Swap),确保状态修改的原子性。例如:
- synchronized轻量级锁通过CAS替换对象头指针。
- ReentrantLock通过CAS修改AQS的state变量。
2. 线程状态管理
- 阻塞状态(BLOCKED):获取锁失败时,线程被挂起(如进入Monitor的Entry List或AQS的CLH队列)。
- 唤醒机制:锁释放后,JVM或AQS从队列中唤醒线程重新竞争锁。
四、示例:获取锁的代码级判断
1. synchronized场景
synchronized (lock) {
// 若当前线程的ID与对象头Mark Word中记录的线程ID一致,则直接进入代码块
}
- 底层动作:JVM检查对象头标志位,若为偏向锁且线程ID匹配,则直接获取锁。
2. ReentrantLock场景
ReentrantLock lock = new ReentrantLock();
lock.lock(); // 内部通过AQS的tryAcquire()方法判断state是否为0
- 底层动作:调用
tryAcquire()方法,若state=0且CAS成功,则获取锁;否则加入队列。
五、如何验证是否获取到锁?
- 显式锁(如ReentrantLock):
- 使用
isHeldByCurrentThread()方法直接判断。
- 使用
- 隐式锁(synchronized):
- 通过线程状态间接判断(如持有锁的线程能执行同步代码块)。
总结
“获取到了锁”的本质是线程通过原子操作修改锁状态标识(如对象头、AQS的state),并记录自身为锁持有者。这一过程依赖硬件级原子指令(CAS)和操作系统级线程调度,而非抽象概念。理解具体锁类型的底层数据结构(如Mark Word、AQS队列)是掌握锁机制的关键。

浙公网安备 33010602011771号