ReentrantLock类的概念
ReentrantLock是Java中的一个可重入的互斥锁类,它提供了比synchronized关键字更灵活的锁定机制。ReentrantLock类实现了Lock接口,支持公平锁和非公平锁两种模式。
ReentrantLock与synchronized关键字的区别
-
锁的获取和释放
synchronized关键字在代码块或方法上使用时,锁的获取和释放是自动的,由JVM负责管理。ReentrantLock类需要手动调用lock()方法获取锁,调用unlock()方法释放锁。这种手动管理锁的方式提供了更大的灵活性,但也增加了出错的风险。
-
公平性
synchronized关键字实现的锁是非公平锁,即线程获取锁的顺序不保证是按照请求锁的顺序。ReentrantLock类可以选择公平锁或非公平锁。公平锁会按照线程请求锁的顺序分配锁,而非公平锁则不保证这一点。
-
锁的粒度
synchronized关键字只能用于代码块或方法级别的锁。ReentrantLock类提供了更细粒度的锁控制,可以通过调用lock()和unlock()方法来精确控制锁的范围。
-
条件变量
synchronized关键字不支持条件变量,无法实现复杂的线程等待/通知机制。ReentrantLock类提供了Condition接口,支持创建多个条件变量,可以实现复杂的线程等待/通知机制。
在多线程环境下如何选择使用
- 如果是在单线程环境下,或者虽然有多个线程但不会发生竞争条件,使用
synchronized关键字就可以满足需求。 - 如果是在多线程环境下,并且需要更灵活的锁控制、公平锁、条件变量等特性,推荐使用
ReentrantLock类。
示例代码
以下是使用ReentrantLock和synchronized关键字实现线程安全的计数器的示例代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
public synchronized void incrementSynchronized() {
count++;
}
public synchronized int getCountSynchronized() {
return count;
}
public static void main(String[] args) {
LockExample lockExample = new LockExample();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
lockExample.increment();
lockExample.incrementSynchronized();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count using ReentrantLock: " + lockExample.getCount());
System.out.println("Count using synchronized: " + lockExample.getCountSynchronized());
}
}
总结
ReentrantLock类提供了更灵活的锁机制,适用于需要更细粒度的锁控制、公平锁、条件变量等特性的场景。与synchronized关键字相比,ReentrantLock类提供了更多的控制选项,但也增加了出错的风险。在多线程环境下,根据具体需求选择合适的锁机制。


被折叠的 条评论
为什么被折叠?



