深入解析ReentrantLock源码与实现机制

需积分: 10 3 下载量 30 浏览量 更新于2024-09-09 收藏 550KB PDF 举报
"深入解析Java并发包中的ReentrantLock源码" ReentrantLock,作为Java并发编程中的核心组件,是可重入的显式锁,它由Java的并发包(java.util.concurrent.locks)提供。这个锁是基于AbstractQueuedSynchronizer(AQS)抽象类实现的,AQS是一个强大的同步框架,它使用一个int类型的`state`字段来表示同步状态,并通过FIFO(先进先出)的等待队列管理那些无法立即获得锁的线程。 1. **ReentrantLock的特性** - **可重入性**:持有锁的线程可以再次获取该锁,不会造成死锁。这是通过记录锁的拥有者(exclusiveOwnerThread)来实现的。 - **公平与非公平**:ReentrantLock支持公平锁和非公平锁两种模式。公平锁保证了线程按照它们在等待队列中的顺序获取锁,而非公平锁则不保证这一点,可能会有线程插队。 - **尝试获取锁**:`tryLock()`方法尝试无阻塞地获取锁,而`tryLock(long, TimeUnit)`则在指定时间后返回是否获取到锁。 - **可中断**:`lockInterruptibly()`方法允许线程在等待时被中断。 - **可轮询**:`lock()`方法会一直尝试获取锁,直到成功,是一种轮询方式。 2. **AQS关键组件** - **head**:等待队列的头部节点,表示当前持有锁的线程。 - **tail**:等待队列的尾部节点,新加入的等待线程会被添加到队尾。 - **state**:同步状态,表示锁的持有情况,当state为0时,锁未被持有;否则表示持有锁的次数。 3. **AQS关键方法** - `tryAcquire(int arg)`:尝试获取独占模式的锁,由子类实现。 - `tryRelease(int arg)`:尝试释放独占模式的锁,子类必须实现。 - `tryAcquireShared(int arg)`:尝试获取共享模式的锁,用于实现读写锁等。 - `tryReleaseShared(int arg)`:尝试释放共享模式的锁。 - `isHeldExclusively()`:判断当前线程是否独占锁。 4. **ReentrantLock的实现** - `NonfairSync`:非公平锁的实现,`lock()`方法直接调用`tryAcquire()`尝试获取锁,没有保证公平性。 - `FairSync`:公平锁的实现,在尝试获取锁之前会检查当前是否有线程在等待。 5. **Node节点** - **waitStatus**:节点的状态,包括CANCELLED、SIGNAL、CONDITION、PROPAGATE等,用于处理线程取消、唤醒等操作。 - **prev** 和 **next**:表示节点在等待队列中的位置,用于链表操作。 - **thread**:等待线程,存储持有节点的线程对象。 - **nextWaiter**:用于条件队列,当线程在条件上等待时,指向下一个等待的节点。 6. **使用示例** - 创建ReentrantLock实例,默认是非公平锁:`ReentrantLock lock = new ReentrantLock();` - 创建公平锁:`ReentrantLock lock = new ReentrantLock(true);` - 获取锁:`lock.lock();` - 尝试获取锁:`lock.tryLock();` - 定时获取锁:`lock.tryLock(10, TimeUnit.SECONDS);` - 可中断获取锁:`try { lock.lockInterruptibly(); } catch (InterruptedException e) { // handle interruption }` - 释放锁:`lock.unlock();` 7. **总结** ReentrantLock提供了更细粒度的控制和更高的性能,适合复杂的并发场景。理解其源码有助于我们更好地理解和优化并发代码,避免潜在的并发问题。