当前位置:首页 > Java > 正文

深入理解ReentrantLock(Java并发编程中的可重入锁详解)

Java并发编程中,线程安全是一个核心问题。为了确保多个线程访问共享资源时不会发生数据不一致或竞态条件,Java提供了多种同步机制。其中,ReentrantLock 是一个强大且灵活的工具,它属于 java.util.concurrent.locks 包,是实现 可重入锁 的关键类。

什么是 ReentrantLock?

ReentrantLock 是 Java 提供的一种显式锁(Explicit Lock),与 synchronized 关键字不同,它需要程序员手动获取和释放锁。它的“可重入”特性意味着:同一个线程可以多次获取同一把锁而不会造成死锁。

深入理解ReentrantLock(Java并发编程中的可重入锁详解) ReentrantLock Java并发编程 可重入锁 线程安全 第1张

ReentrantLock 的基本使用

使用 ReentrantLock 需要遵循以下步骤:

  1. 创建 ReentrantLock 对象
  2. 在需要同步的代码块前调用 lock() 方法获取锁
  3. finally 块中调用 unlock() 方法释放锁(非常重要!)

下面是一个简单的示例:

import java.util.concurrent.locks.ReentrantLock;public class Counter {    private int count = 0;    private final ReentrantLock lock = new ReentrantLock();    public void increment() {        lock.lock();  // 获取锁        try {            count++;  // 临界区代码        } finally {            lock.unlock();  // 释放锁        }    }    public int getCount() {        lock.lock();        try {            return count;        } finally {            lock.unlock();        }    }}

为什么要在 finally 块中释放锁?

如果在 lock()unlock() 之间发生异常,程序可能跳过 unlock(),导致锁永远无法释放,其他线程将永远等待——这就是死锁。因此,必须finally 块中释放锁,以确保即使发生异常也能正确释放。

ReentrantLock vs synchronized

| 特性 | ReentrantLock | synchronized ||------|----------------|---------------|| 锁获取方式 | 显式(需手动 lock/unlock) | 隐式(JVM 自动管理) || 可中断 | 支持(tryLock、lockInterruptibly) | 不支持 || 超时机制 | 支持(tryLock(timeout)) | 不支持 || 公平锁 | 支持(构造函数参数) | 不支持 || 条件变量 | 支持(newCondition()) | 仅 wait/notify | ReentrantLock 提供了比 synchronized 更丰富的功能,但也更易出错(如忘记 unlock)。因此,在简单场景下,synchronized 仍是首选;在需要高级功能(如超时、公平锁)时,才考虑使用 ReentrantLock

公平锁与非公平锁

ReentrantLock 默认是非公平锁(性能更好),但你可以通过构造函数启用公平锁:

// 公平锁ReentrantLock fairLock = new ReentrantLock(true);// 非公平锁(默认)ReentrantLock unfairLock = new ReentrantLock();

公平锁保证等待时间最长的线程优先获取锁,避免线程饥饿,但吞吐量较低。非公平锁允许插队,效率更高,但可能导致某些线程长时间等待。

总结

ReentrantLockJava并发编程 中实现 线程安全 的重要工具。它提供了比 synchronized 更灵活的控制能力,包括可中断锁、超时锁、公平锁和多条件变量等。然而,使用时务必注意在 finally 块中释放锁,避免死锁。

掌握 ReentrantLock可重入锁 的原理,将帮助你编写更高效、更可靠的并发程序。对于初学者来说,建议先从 synchronized 入手,再逐步过渡到 ReentrantLock 的高级用法。