Java 语言 可重入锁 ReentrantLock 与synchronized对比 公平锁与非公平锁

Java阿木 发布于 2025-06-25 8 次阅读


摘要:

在Java并发编程中,锁是保证线程安全的重要机制。ReentrantLock和synchronized是Java中两种常见的锁机制。本文将围绕ReentrantLock与synchronized,对比分析公平锁与非公平锁的特点、实现原理以及在实际应用中的选择。

一、

在多线程环境中,为了保证数据的一致性和线程安全,需要使用锁来控制对共享资源的访问。Java提供了两种锁机制:synchronized和ReentrantLock。其中,ReentrantLock是Java 5引入的,它提供了比synchronized更丰富的功能,包括公平锁和非公平锁。本文将对比分析这两种锁机制,探讨公平锁与非公平锁的特点和适用场景。

二、synchronized简介

synchronized是Java中的一种内置锁,它是一种非公平锁。当一个线程访问一个由synchronized修饰的方法或代码块时,它会先尝试获取锁。如果锁已经被其他线程持有,则当前线程会等待,直到锁被释放。synchronized的语法如下:

java

synchronized (object) {


// 需要同步的代码块


}


或者

java

synchronized (this) {


// 需要同步的代码块


}


其中,object可以是任何对象,this表示当前对象。

三、ReentrantLock简介

ReentrantLock是Java 5引入的一种可重入锁,它提供了比synchronized更丰富的功能。ReentrantLock可以创建公平锁和非公平锁,并且提供了锁的获取和释放的更多控制。ReentrantLock的语法如下:

java

Lock lock = new ReentrantLock();


try {


lock.lock();


// 需要同步的代码块


} finally {


lock.unlock();


}


四、公平锁与非公平锁对比

1. 公平锁

公平锁是指线程按照请求锁的顺序来获得锁。在ReentrantLock中,可以通过构造函数设置锁的公平性:

java

Lock fairLock = new ReentrantLock(true); // 创建公平锁


公平锁的优点是线程按照请求锁的顺序获得锁,这可以减少线程间的竞争,降低死锁的风险。公平锁的缺点是可能会降低程序的性能,因为线程需要等待其他线程释放锁。

2. 非公平锁

非公平锁是指线程在尝试获取锁时,不按照请求锁的顺序,而是尝试直接获取锁。在ReentrantLock中,默认情况下创建的是非公平锁:

java

Lock nonfairLock = new ReentrantLock(); // 创建非公平锁


非公平锁的优点是线程在获取锁时不会等待其他线程,这可以提高程序的性能。非公平锁可能会增加死锁的风险,因为线程可能会在竞争锁时发生冲突。

五、实际应用中的选择

在实际应用中,选择公平锁还是非公平锁取决于具体场景和需求。以下是一些选择建议:

1. 如果程序对性能要求较高,且线程竞争不激烈,可以选择非公平锁。

2. 如果程序对性能要求不高,且线程竞争激烈,或者需要降低死锁的风险,可以选择公平锁。

3. 如果程序需要更细粒度的锁控制,例如尝试非阻塞地获取锁,可以使用ReentrantLock。

六、总结

本文对比分析了Java中的ReentrantLock和synchronized,探讨了公平锁与非公平锁的特点和适用场景。在实际应用中,应根据具体需求和场景选择合适的锁机制,以保证程序的性能和线程安全。

以下是一个简单的示例代码,展示如何使用ReentrantLock创建公平锁和非公平锁:

java

public class LockExample {


private final Lock fairLock = new ReentrantLock(true); // 公平锁


private final Lock nonfairLock = new ReentrantLock(); // 非公平锁

public void fairLockMethod() {


fairLock.lock();


try {


// 需要同步的代码块


} finally {


fairLock.unlock();


}


}

public void nonfairLockMethod() {


nonfairLock.lock();


try {


// 需要同步的代码块


} finally {


nonfairLock.unlock();


}


}


}


通过以上代码,我们可以看到如何使用ReentrantLock创建公平锁和非公平锁,并在方法中使用它们来同步代码块。