ReentrantLock源码解析
发布时间: 2024-01-10 14:05:55 阅读量: 9 订阅数: 17
# 1. 【ReentrantLock源码解析】
## 1. 简介
### 1.1 什么是ReentrantLock
ReentrantLock是Java提供的一种可重入的互斥锁,它可以用于替代synchronized关键字。相较于synchronized,ReentrantLock提供了更多的灵活性和功能。
### 1.2 ReentrantLock的作用和特点
ReentrantLock用于保护临界区,防止多个线程同时访问共享资源造成数据不一致或错误的情况。它具有以下特点:
- 可重入:同一个线程可以多次获得同一个锁,避免死锁的发生。
- 公平性:可以选择公平性或非公平性的锁获取方式。
- 等待可中断:提供了可中断响应的锁等待方式。
- 条件变量:提供了Condition接口来实现线程间的等待和唤醒机制。
### 1.3 为什么使用ReentrantLock
ReentrantLock相对于synchronized关键字有以下优点:
- 可中断:当线程在等待锁时,可以根据需要中断等待,而synchronized关键字不具备这个功能。
- 公平性:可以选择公平性或非公平性的锁获取方式,而synchronized关键字只能是非公平的。
- 等待超时:可以在获取锁时设置等待超时时间,而synchronized关键字没有提供这个功能。
- 条件变量:提供了Condition接口来实现线程间的等待和唤醒机制,可以更灵活地控制线程的执行顺序。
## 2. 基本用法
ReentrantLock的基本用法主要包括创建ReentrantLock对象、获取锁、释放锁、条件变量等操作。
### 2.1 创建ReentrantLock对象
使用ReentrantLock的第一步是创建ReentrantLock对象,可以选择公平性或非公平性的锁获取方式。
```java
ReentrantLock lock = new ReentrantLock(); // 创建非公平锁
ReentrantLock fairLock = new ReentrantLock(true); // 创建公平锁
```
### 2.2 lock方法和unlock方法
获取锁和释放锁是ReentrantLock的核心操作,可以使用`lock`方法获取锁,使用`unlock`方法释放锁。
```java
lock.lock(); // 获取锁
try {
// 临界区代码
} finally {
lock.unlock(); // 释放锁
}
```
### 2.3 tryLock方法和tryLock带时间限制的方法
使用`tryLock`方法尝试获取锁,如果获取成功返回true,否则返回false,不会阻塞线程。
```java
if (lock.tryLock()) {
try {
// 临界区代码
} finally {
lock.unlock(); // 释放锁
}
} else {
// 无法获取锁的处理
}
```
还可以使用`tryLock`方法的带时间限制的重载版本,在指定的时间范围内尝试获取锁。
```java
if (lock.tryLock(timeout, TimeUnit.MILLISECONDS)) {
try {
// 临界区代码
} finally {
lock.unlock(); // 释放锁
}
} else {
// 在指定时间内无法获取锁的处理
}
```
### 2.4 锁的重入性
ReentrantLock允许同一个线程多次获取同一个锁,这种特性称为锁的重入性。可以避免死锁的发生,提高代码灵活性。
```java
lock.lock(); // 第一次获取锁
try {
// 临界区代码
lock.lock(); // 第二次获取锁
try {
// 临界区代码
} finally {
lock.unlock(); // 第二次释放锁
}
} finally {
lock.unlock(); // 第一次释放锁
}
```
这样,同一个线程内部就可以多次获取和释放锁,保证了线程对共享资源的正确访问。
继续阅读下一章节:【3. 公平性与非公平性】
# 2. 基本用法
ReentrantLock提供了一些基本的方法,用于加锁和释放锁。
### 2.1 创建ReentrantLock对象
要使用ReentrantLock,首先需要创建一个ReentrantLock对象。可以使用无参构造函数来创建一个非公平锁(默认),或者使用带有布尔值参数的构造函数来创建一个公平锁。
```java
// 创建一个非公平锁
ReentrantLock lock = new ReentrantLock();
// 创建一个公平锁
ReentrantLock fairLock = new ReentrantLock(true);
```
### 2.2 lock方法和unlock方法
`lock`方法用于获取锁,若锁已被其他线程占用,则当前线程会被阻塞直至获取到锁为止。
`unlock`方法用于释放锁,需要确保在每次获取到锁后,都会对应地释放锁,以免造成资源泄露。
下面是一个简单的示例代码:
```java
class MyTask implements Runnable {
private ReentrantLock lock;
public MyTask(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.lock(); // 获取锁
try {
// 执行需要加锁保护的代码
// ...
} finally {
lock.unlock(); // 释放锁
}
}
}
public class Main {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
MyTask task = new MyTask(lock);
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
}
}
```
### 2.3 tryLock方法和tryLock带时间限制的方法
`tryLock`方法尝试获取锁,如果锁可用,则获取到锁并立即返回`true`,如果锁不可用,则立即返回`false`,而不会阻塞当前线程。
`tryLock(long timeout, TimeUnit unit)`方法与`tryLock`方法类似,但是它会在一段时间内尝试获取锁,如果超过指定时间仍未获取到锁,则返回`false`。
下面的示例代码演示了如何使用`tryLock`方法:
```java
class MyTask implements Runnable {
private ReentrantLock lock;
public MyTask(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
if (lock.tryLock()) { // 尝试获取锁
try {
// 执行需要加锁保护的代码
// ...
} finally {
lock.unlock(); // 释放锁
}
} else {
// 获取锁失败,进行其他处理
// ...
}
}
}
public class Main {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
MyTask task = new MyTask(lock);
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
}
}
```
### 2.4 锁的重入性
ReentrantLock是可重入锁,支持多次加锁和解锁。在同一个线程中,可以多次调用`lock`方法,而不会出现死锁。
```java
class MyTask implements Runnable {
private ReentrantLock lock;
public MyTask(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.lock(); // 第一次获取锁
try {
System.out.println("Thread " + Thread.currentThread().getId() + " acquired the lock for the first time.");
lock.lock(); // 第二次获取锁
try {
System.out.println("Thread " + Thread.currentThread().getId() + " acquired the lock again.");
// 执行需要加锁保护的代码
// ...
} finally {
lock.unlock(); // 第二次释放锁
System.out.println("Thread " + Thread.currentThread().getId() + " released the lock again.");
}
} finally {
lock.unlock(); // 第一次释放锁
System.out.println("Thread " + Thread.currentThread().getId() + " released the lock for the first time.");
}
}
}
publ
```
0
0