reentrantlock原理

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`

ReentrantLock 原理

ReentrantLock 是 Java 中的一个高级同步机制,它提供了比传统的 synchronized 方法和语句更丰富的操作。它属于 java.util.concurrent.locks 包下的一个类。ReentrantLock 允许一个线程多次获得同一把锁,即是可重入的。

基本原理

ReentrantLock 内部通过使用一个同步器(AbstractQueuedSynchronizer,简称 AQS)来实现锁的功能。AQS 使用一个整型的 volatile 变量(称为 state)来表示同步状态,以及一个 FIFO 队列来管理那些等待获取锁的线程。

状态(State)

  • 当 state 为 0 时,表示锁没有被任何线程持有。

  • 当 state 大于 0 时,表示锁被一个线程持有,并且 state 表示该线程获取锁的次数。

可重入性

  • ReentrantLock 是可重入的,即如果当前线程已经持有锁,再次请求锁时会立即成功,并且 state 会相应地增加。

  • 当线程释放锁时,它会减少 state 的值。当 state 为 0 时,锁被完全释放。

锁的获取与释放

  • 获取锁:当一个线程尝试获取锁时,如果 state 为 0,AQS 会将 state 设置为 1 并且设置当前线程为锁的持有者。如果当前线程已经持有锁(即尝试重入),AQS 会增加 state 的值。

  • 释放锁:当线程释放锁时,它会调用 unlock() 方法,AQS 会减少 state 的值。如果 state 为 0,则锁被完全释放,并且可能会唤醒在等待队列中等待这个锁的其他线程。

公平性和非公平性

ReentrantLock 提供了公平锁和非公平锁两种模式:

  • 公平锁:在这种模式下,锁会按照线程在等待队列中的等待顺序来分配,即“先来先服务”。

  • 非公平锁:在这种模式下,当锁可用时,任何请求它的线程都有机会获取锁,这可能会导致“线程饥饿”。

方法概览

ReentrantLock 提供了一些重要的方法:

  • lock(): 获取锁,如果锁不可用则等待。

  • unlock(): 释放锁。

  • tryLock(): 尝试获取锁,如果锁可用立即返回 true,否则返回 false。

  • tryLock(long timeout, TimeUnit unit): 在给定的时间内尝试获取锁,如果在指定的时间内获取到锁则返回 true,否则返回 false。

  • lockInterruptibly(): 获取锁,但优先响应中断。

代码示例

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void performAction() {
        lock.lock(); // 获取锁
        try {
            // 临界区代码
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

在上面的代码示例中,我们创建了一个 ReentrantLock 实例,并在 performAction 方法中使用它来保护临界区代码。通过在 try 块中编写业务逻辑,并在 finally 块中释放锁,我们确保了即使在发生异常的情况下,锁也会被释放。

总结来说,ReentrantLock 是一个强大的同步工具,它提供了比 synchronized 更细粒度的锁控制,包括尝试获取锁、定时锁等待和中断等待锁的能力,同时还支持公平性选择。

最后更新于