reentrantLock.lock
时间: 2024-09-21 09:03:21 浏览: 56
`ReentrantLock.lock()` 是 Java 中 `ReentrantLock` 类的一个方法,它是互斥锁(mutex)的一种实现,用于同步代码块或方法的执行。`ReentrantLock` 是 `java.util.concurrent.locks` 包下的线程安全锁,相比于 `synchronized` 关键字,它提供了更细粒度的控制以及更高的并发性能。
当你调用 `lock()` 方法时,如果当前锁未被其他线程持有,那么这个线程会获得锁,并进入锁定状态。如果锁已经被另一个线程持有,则该方法会阻塞,直到锁释放。一旦获取到锁,你可以通过 `tryLock(long timeout, TimeUnit unit)` 来尝试快速获取锁,在指定的时间内如果无法获得则返回失败。
`lock()` 方法的使用通常配合 `unlock()` 方法,确保在使用完共享资源后释放锁,以便其他线程可以继续执行。这是一个基本的锁定和解锁流程示例:
```java
ReentrantLock lock = new ReentrantLock();
lock.lock(); // 获取锁
try {
// 执行需要同步的代码
} finally {
lock.unlock(); // 释放锁
}
```
相关问题
ReentrantLock.lock
### Java ReentrantLock `lock` 方法的使用说明
#### 1. **基本概念**
ReentrantLock 是 Java 中用于实现显式锁定的一种工具,它提供了一种更灵活的方式来管理线程间的同步操作。相比 synchronized 关键字,ReentrantLock 提供了更多功能和选项,例如支持公平锁、可中断等待以及超时获取锁等功能。
当调用 `lock()` 方法时,当前线程会尝试获取锁。如果锁已经被其他线程持有,则当前线程会被阻塞直到获得该锁为止[^4]。
---
#### 2. **核心行为**
- 调用 `lock.lock()` 后,线程进入独占模式并阻止其他线程访问被保护的资源。
- 如果多个线程竞争同一个锁,默认情况下遵循非公平策略(即不按请求顺序分配),除非创建锁时指定了公平性参数[^2]。
- 锁定逻辑应始终配对解锁逻辑,在任何可能抛出异常的情况下都需确保释放锁,因此推荐将 `unlock()` 放置在 `finally` 块中[^3]。
---
#### 3. **示例代码**
以下是基于 ReentrantLock 的典型应用场景:
```java
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(); // 确保最终释放锁
}
}
}
```
上述代码展示了如何利用 `lock()` 和 `unlock()` 来保证共享变量的安全访问。无论是否发生异常,`finally` 都能保障锁被及时释放[^1]。
---
#### 4. **注意事项**
- 若未正确调用 `unlock()`,可能导致死锁或其他并发问题。务必严格遵守加锁与解锁成对使用的规则。
- 默认构造函数生成的是非公平锁;若希望启用公平锁,可以传递布尔值 true 给构造器:
```java
ReentrantLock fairLock = new ReentrantLock(true);
```
---
#### 5. **与其他机制对比**
虽然 `synchronized` 更简洁易用,但在某些复杂场景下,`ReentrantLock` 显示出了显著优势:
- 它允许程序主动放弃锁争夺(通过 `tryLock()` 实现);
- 支持设置最大等待时间;
- 可配置为公平锁以减少饥饿现象[^5]。
---
package com.company.calcul; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Thread1 { public static void main(String[] args) { ReentrantLock reentrantLock = new ReentrantLock(); Condition condition1 = reentrantLock.newCondition(); Condition condition2 = reentrantLock.newCondition(); Condition condition3 = reentrantLock.newCondition(); Thread threadA = new Thread(() -> { reentrantLock.lock(); try { condition1.await(); System.out.println("A"); condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } }); Thread threadB = new Thread(() -> { reentrantLock.lock(); try { condition2.await(); System.out.println("B"); condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } }); Thread threadC = new Thread(() -> { reentrantLock.lock(); try { condition3.await(); System.out.println("C"); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } }); reentrantLock.lock(); try { threadA.start(); threadB.start(); threadC.start(); condition1.signal(); } finally { reentrantLock.unlock(); } } } 这个为什么没有输出ABC
这段代码没有输出ABC是因为在调用condition1.signal()之前,主线程已经释放了锁。
在代码中,主线程先获取了锁reentrantLock.lock(),然后启动了线程A、B、C,并调用condition1.signal()来唤醒线程A。但是,在调用signal()方法之前,主线程调用了reentrantLock.unlock()释放了锁。
由于线程A、B、C在启动后会尝试获取锁并进入等待状态,而此时主线程已经释放了锁,线程A无法获取到锁并继续执行,所以最终没有输出ABC。
为了修正这个问题,可以将reentrantLock.lock()方法的调用位置移动到condition1.signal()之前,确保在调用signal()方法之前保持锁的持有状态。
修正后的代码如下:
```java
package com.company.calcul;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Thread1 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
Condition condition3 = reentrantLock.newCondition();
Thread threadA = new Thread(() -> {
reentrantLock.lock();
try {
condition1.await();
System.out.println("A");
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
Thread threadB = new Thread(() -> {
reentrantLock.lock();
try {
condition2.await();
System.out.println("B");
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
Thread threadC = new Thread(() -> {
reentrantLock.lock();
try {
condition3.await();
System.out.println("C");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
reentrantLock.lock();
try {
threadA.start();
threadB.start();
threadC.start();
condition1.signal();
} finally {
reentrantLock.unlock();
}
}
}
```
在修正后的代码中,主线程在启动子线程之前获取锁reentrantLock.lock(),然后启动子线程并调用condition1.signal()方法唤醒线程A,最后在finally块中释放锁reentrantLock.unlock()。这样可以确保线程A在调用signal()方法之前已经获取到了锁,并且其他线程也能正确执行并输出ABC。
阅读全文
相关推荐

















