JUC-ReentrantLock实现原理
JUC-ReentrantLock实现原理
xukun什么是ReentrantLock ?
ReentrantLock 其实就是基于 AQS 实现的一个可重入锁,支持公平和非公平两种方式。
内部实现依靠一个 state 变量和两个等待队列:同步队列和等待队列。
利用 CAS 修改 state 来争抢锁。
争抢不到则入同步队列等待,同步队列是一个双向链表。
条件 condition 不满足时候则入等待队列等待,是个单向链表。
是否是公平锁的区别在于:线程获取锁时是加入到同步队列尾部还是直接利用 CAS 争抢锁。
参考图片:
扩展
CAS操作
CAS 是一种硬件级别的原子操作,它比较内存中的某个值是否为预期值,如果是,则更新为新值,否则不做修改。
工作原理:
- 比较(Compare):CAS 会检查内存中的某个值是否与预期值相等。
- 交换(Swap):如果相等,则将内存中的值更新为新值。
- 失败重试:如果不相等,说明有其他线程已经修改了该值,CAS 操作失败,一般会利用重试,直到成功。
自旋锁
自旋锁(Spinlock) 是一种轻量级锁机制。线程在获取锁失败时不会立即进入阻塞状态,而是会在循环中反复尝试获取锁,直到成功。
这种方式避免了线程的上下文切换开销,所以称之为轻量级锁,适用于锁等待时间较短的场景。
以下就是一个简单自旋锁的实现:
1 | public class SpinLock { |
它的优点能避免线程上下文切换的开销,缺点主要有两点:
- 锁饥饿问题:高并发场景,可能存在某个线程一直 CAS 失败,争抢不到锁。
- 性能问题:多核处理器如果对同一变量高并发进行 CAS 操作,会导致总线风暴问题。