共计 1631 个字符,预计需要花费 5 分钟才能阅读完成。
ReentrantLock(可重入锁)是 Java 中的一种同步机制,它提供了与synchronized
关键字相似的功能,但具有更灵活的特性。在多线程编程中,ReentrantLock
允许线程在获取锁之后再次获取同一把锁,而不会导致死锁。
ReentrantLock
具有以下特点:
- 可重入性:
ReentrantLock
是可重入的,这意味着一个线程可以多次获取同一把锁而不会产生死锁。当线程重复获取锁时,它必须相应地释放同样次数的锁,才能完全释放锁资源。
- 互斥性:
ReentrantLock
保证了线程对共享资源的互斥访问。一次只有一个线程可以持有这把锁,其他线程必须等待锁释放才能获得锁。
- 等待可中断:
通过lockInterruptibly()
方法,线程可以在等待锁的过程中被中断,而不是一直阻塞等待。这种特性能够避免线程长时间阻塞,提高系统的响应性。
- 公平性:
ReentrantLock
可以在创建时选择是否公平锁。公平锁是指锁的获取按照请求的顺序进行,而非公平锁则允许插队。公平锁会导致线程切换的开销增加,但能避免饥饿问题。
Sychronized 和 ReentrantLock 比较:
synchronized | ReentrantLock |
---|---|
Java中的一个关键字 | JDK提供的一个类 |
JVM层面的锁 | API层面的锁 |
自动加锁与释放锁 | 需要手动加锁与释放锁 |
不可获取当前线程是否上锁 | 可获取当前线程是否上锁isHeldByCurrentThread |
非公平锁 | 公平锁或非公平锁 |
不可中断 | 可中断 1:调用设置超时方法tryLock(long timeout ,timeUnit unit) 2:调用lockInterruptibly()放到代码块中,然后调用interrupt()方法可以中断 |
锁的是对象,锁信息保存在对象头中 | int类型的state标识来标识锁的状态 |
底层有锁升级过程 | 没有锁升级过程 |
简单实用案例:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockExample example = new ReentrantLockExample();
// 创建并启动两个线程,分别增加计数器的值
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
thread1.start();
thread2.start();
// 等待两个线程执行完毕
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出最终的计数器值
System.out.println("Final Count: " + example.getCount());
}
}
需要注意的是,使用ReentrantLock
时,一定要确保在合适的位置释放锁,通常在finally
块中释放锁以确保不管是否发生异常都能释放锁资源,避免死锁情况。
提醒:本文发布于136天前,文中所关联的信息可能已发生改变,请知悉!