1. ReentrantLock概述

ReentrantLock是Java并发包中提供的高级锁机制,相比synchronized关键字,它提供了更灵活的锁控制能力。本文将详细介绍ReentrantLock的使用方法,包括锁机制、条件变量、公平锁、读写锁的完整解决方案。

1.1 核心功能

  1. 可重入性: 同一线程可以多次获取同一把锁
  2. 公平性: 支持公平锁和非公平锁
  3. 条件变量: 提供Condition接口实现线程等待和通知
  4. 中断响应: 支持锁获取的中断操作
  5. 超时机制: 支持锁获取的超时控制

1.2 技术架构

1
2
3
4
线程A → 获取锁 → 执行临界区代码 → 释放锁
线程B → 等待锁 → 获取锁 → 执行临界区代码 → 释放锁
↓ ↓ ↓ ↓
竞争 → 队列管理 → 锁状态 → 条件通知

2. Maven依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!-- pom.xml -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.lock</groupId>
<artifactId>reentrant-lock-demo</artifactId>
<version>1.0.0</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>

<properties>
<java.version>11</java.version>
</properties>

<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Commons工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>

<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>

<!-- Micrometer(监控指标) -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

3. 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# application.yml
server:
port: 8080

spring:
application:
name: reentrant-lock-demo

# 锁配置
lock:
# 公平锁配置
fair:
enabled: true
timeout: 5000

# 非公平锁配置
unfair:
enabled: false
timeout: 3000

# 读写锁配置
read-write:
read-timeout: 2000
write-timeout: 5000

# 监控配置
management:
endpoints:
web:
exposure:
include: "*"
metrics:
export:
prometheus:
enabled: true

4. 基础锁服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package com.lock.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
* 基础锁服务
* @author Java实战
*/
@Slf4j
@Service
public class BasicLockService {

/**
* 非公平锁
*/
private final ReentrantLock unfairLock = new ReentrantLock();

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

/**
* 共享资源
*/
private int sharedResource = 0;

/**
* 使用非公平锁保护共享资源
*/
public void incrementWithUnfairLock() {
unfairLock.lock();
try {
log.info("线程 {} 获取非公平锁", Thread.currentThread().getName());

// 模拟业务处理
Thread.sleep(100);
sharedResource++;

log.info("共享资源值: {}, 线程: {}", sharedResource, Thread.currentThread().getName());

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("线程被中断", e);
} finally {
unfairLock.unlock();
log.info("线程 {} 释放非公平锁", Thread.currentThread().getName());
}
}

/**
* 使用公平锁保护共享资源
*/
public void incrementWithFairLock() {
fairLock.lock();
try {
log.info("线程 {} 获取公平锁", Thread.currentThread().getName());

// 模拟业务处理
Thread.sleep(100);
sharedResource++;

log.info("共享资源值: {}, 线程: {}", sharedResource, Thread.currentThread().getName());

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("线程被中断", e);
} finally {
fairLock.unlock();
log.info("线程 {} 释放公平锁", Thread.currentThread().getName());
}
}

/**
* 尝试获取锁(非阻塞)
*/
public boolean tryIncrementWithLock() {
if (unfairLock.tryLock()) {
try {
log.info("线程 {} 成功获取锁", Thread.currentThread().getName());

// 模拟业务处理
Thread.sleep(100);
sharedResource++;

log.info("共享资源值: {}, 线程: {}", sharedResource, Thread.currentThread().getName());
return true;

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("线程被中断", e);
return false;
} finally {
unfairLock.unlock();
log.info("线程 {} 释放锁", Thread.currentThread().getName());
}
} else {
log.info("线程 {} 未能获取锁,执行其他操作", Thread.currentThread().getName());
return false;
}
}

/**
* 超时获取锁
*/
public boolean incrementWithTimeoutLock(long timeout, TimeUnit unit) {
try {
if (unfairLock.tryLock(timeout, unit)) {
try {
log.info("线程 {} 在 {} {} 内成功获取锁",
Thread.currentThread().getName(), timeout, unit);

// 模拟业务处理
Thread.sleep(100);
sharedResource++;

log.info("共享资源值: {}, 线程: {}", sharedResource, Thread.currentThread().getName());
return true;

} finally {
unfairLock.unlock();
log.info("线程 {} 释放锁", Thread.currentThread().getName());
}
} else {
log.warn("线程 {} 在 {} {} 内未能获取锁",
Thread.currentThread().getName(), timeout, unit);
return false;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("线程被中断", e);
return false;
}
}

/**
* 可中断获取锁
*/
public void incrementWithInterruptibleLock() throws InterruptedException {
unfairLock.lockInterruptibly();
try {
log.info("线程 {} 获取可中断锁", Thread.currentThread().getName());

// 模拟长时间业务处理
Thread.sleep(5000);
sharedResource++;

log.info("共享资源值: {}, 线程: {}", sharedResource, Thread.currentThread().getName());

} finally {
unfairLock.unlock();
log.info("线程 {} 释放可中断锁", Thread.currentThread().getName());
}
}

/**
* 获取锁状态信息
*/
public LockStatus getLockStatus() {
return LockStatus.builder()
.isLocked(unfairLock.isLocked())
.isHeldByCurrentThread(unfairLock.isHeldByCurrentThread())
.queueLength(unfairLock.getQueueLength())
.holdCount(unfairLock.getHoldCount())
.isFair(unfairLock.isFair())
.build();
}

/**
* 获取共享资源值
*/
public int getSharedResource() {
return sharedResource;
}

/**
* 锁状态信息
*/
@lombok.Data
@lombok.Builder
public static class LockStatus {
private boolean isLocked;
private boolean isHeldByCurrentThread;
private int queueLength;
private int holdCount;
private boolean isFair;
}
}

5. 条件变量服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package com.lock.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
* 条件变量服务
* @author Java实战
*/
@Slf4j
@Service
public class ConditionService {

private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();

/**
* 共享数据
*/
private int data = 0;
private boolean dataReady = false;

/**
* 生产者:等待条件满足后生产数据
*/
public void produceData(int value) {
lock.lock();
try {
log.info("生产者开始生产数据: {}", value);

// 等待条件:数据未准备好
while (dataReady) {
log.info("数据已准备好,生产者等待...");
condition.await();
}

// 生产数据
data = value;
dataReady = true;

log.info("生产者完成数据生产: {}", data);

// 通知消费者
condition.signal();

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("生产者被中断", e);
} finally {
lock.unlock();
}
}

/**
* 消费者:等待数据准备好后消费
*/
public int consumeData() {
lock.lock();
try {
log.info("消费者开始消费数据");

// 等待条件:数据准备好
while (!dataReady) {
log.info("数据未准备好,消费者等待...");
condition.await();
}

// 消费数据
int result = data;
dataReady = false;

log.info("消费者完成数据消费: {}", result);

// 通知生产者
condition.signal();

return result;

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("消费者被中断", e);
return -1;
} finally {
lock.unlock();
}
}

/**
* 超时等待条件
*/
public boolean waitForConditionWithTimeout(long timeout, TimeUnit unit) {
lock.lock();
try {
log.info("等待条件满足,超时时间: {} {}", timeout, unit);

boolean result = condition.await(timeout, unit);

if (result) {
log.info("条件满足,继续执行");
} else {
log.warn("等待超时,条件未满足");
}

return result;

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("等待被中断", e);
return false;
} finally {
lock.unlock();
}
}

/**
* 通知所有等待的线程
*/
public void signalAll() {
lock.lock();
try {
log.info("通知所有等待的线程");
condition.signalAll();
} finally {
lock.unlock();
}
}

/**
* 通知一个等待的线程
*/
public void signal() {
lock.lock();
try {
log.info("通知一个等待的线程");
condition.signal();
} finally {
lock.unlock();
}
}

/**
* 获取数据状态
*/
public DataStatus getDataStatus() {
lock.lock();
try {
return DataStatus.builder()
.data(data)
.dataReady(dataReady)
.build();
} finally {
lock.unlock();
}
}

/**
* 数据状态
*/
@lombok.Data
@lombok.Builder
public static class DataStatus {
private int data;
private boolean dataReady;
}
}

6. 读写锁服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.lock.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* 读写锁服务
* @author Java实战
*/
@Slf4j
@Service
public class ReadWriteLockService {

private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

/**
* 共享数据
*/
private String sharedData = "初始数据";
private int readCount = 0;
private int writeCount = 0;

/**
* 读操作
*/
public String readData() {
readWriteLock.readLock().lock();
try {
readCount++;
log.info("线程 {} 开始读数据,读次数: {}", Thread.currentThread().getName(), readCount);

// 模拟读操作
Thread.sleep(100);

log.info("线程 {} 读取到数据: {}", Thread.currentThread().getName(), sharedData);
return sharedData;

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("读操作被中断", e);
return null;
} finally {
readWriteLock.readLock().unlock();
log.info("线程 {} 释放读锁", Thread.currentThread().getName());
}
}

/**
* 写操作
*/
public void writeData(String newData) {
readWriteLock.writeLock().lock();
try {
writeCount++;
log.info("线程 {} 开始写数据,写次数: {}", Thread.currentThread().getName(), writeCount);

// 模拟写操作
Thread.sleep(200);

sharedData = newData;
log.info("线程 {} 写入数据: {}", Thread.currentThread().getName(), sharedData);

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("写操作被中断", e);
} finally {
readWriteLock.writeLock().unlock();
log.info("线程 {} 释放写锁", Thread.currentThread().getName());
}
}

/**
* 尝试获取读锁
*/
public boolean tryReadData() {
if (readWriteLock.readLock().tryLock()) {
try {
readCount++;
log.info("线程 {} 成功获取读锁,读次数: {}", Thread.currentThread().getName(), readCount);

Thread.sleep(100);
log.info("线程 {} 读取到数据: {}", Thread.currentThread().getName(), sharedData);

return true;

} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("读操作被中断", e);
return false;
} finally {
readWriteLock.readLock().unlock();
log.info("线程 {} 释放读锁", Thread.currentThread().getName());
}
} else {
log.info("线程 {} 未能获取读锁", Thread.currentThread().getName());
return false;
}
}

/**
* 超时获取写锁
*/
public boolean tryWriteDataWithTimeout(String newData, long timeout, TimeUnit unit) {
try {
if (readWriteLock.writeLock().tryLock(timeout, unit)) {
try {
writeCount++;
log.info("线程 {} 在 {} {} 内成功获取写锁,写次数: {}",
Thread.currentThread().getName(), timeout, unit, writeCount);

Thread.sleep(200);
sharedData = newData;

log.info("线程 {} 写入数据: {}", Thread.currentThread().getName(), sharedData);
return true;

} finally {
readWriteLock.writeLock().unlock();
log.info("线程 {} 释放写锁", Thread.currentThread().getName());
}
} else {
log.warn("线程 {} 在 {} {} 内未能获取写锁",
Thread.currentThread().getName(), timeout, unit);
return false;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("写操作被中断", e);
return false;
}
}

/**
* 获取读写锁状态
*/
public ReadWriteLockStatus getReadWriteLockStatus() {
return ReadWriteLockStatus.builder()
.readLockCount(readCount)
.writeLockCount(writeCount)
.isWriteLocked(readWriteLock.writeLock().isHeldByCurrentThread())
.isReadLocked(readWriteLock.readLock().isHeldByCurrentThread())
.sharedData(sharedData)
.build();
}

/**
* 读写锁状态
*/
@lombok.Data
@lombok.Builder
public static class ReadWriteLockStatus {
private int readLockCount;
private int writeLockCount;
private boolean isWriteLocked;
private boolean isReadLocked;
private String sharedData;
}
}

7. 锁监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.lock.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.concurrent.locks.ReentrantLock;

/**
* 锁监控服务
* @author Java实战
*/
@Slf4j
@Service
public class LockMonitorService {

private final ReentrantLock monitorLock = new ReentrantLock();

/**
* 锁使用统计
*/
private long lockAcquireCount = 0;
private long lockReleaseCount = 0;
private long lockWaitTime = 0;

/**
* 监控锁使用情况(每30秒)
*/
@Scheduled(fixedRate = 30000)
public void monitorLockUsage() {
log.info("=== 锁使用监控报告 ===");

monitorLock.lock();
try {
log.info("锁获取次数: {}", lockAcquireCount);
log.info("锁释放次数: {}", lockReleaseCount);
log.info("平均等待时间: {} ms",
lockAcquireCount > 0 ? lockWaitTime / lockAcquireCount : 0);

// 检查锁状态
if (monitorLock.isLocked()) {
log.warn("监控锁当前被持有");
}

if (monitorLock.getQueueLength() > 0) {
log.warn("有 {} 个线程在等待锁", monitorLock.getQueueLength());
}

} finally {
monitorLock.unlock();
}

log.info("=== 监控报告结束 ===");
}

/**
* 记录锁获取
*/
public void recordLockAcquire(long waitTime) {
monitorLock.lock();
try {
lockAcquireCount++;
lockWaitTime += waitTime;
} finally {
monitorLock.unlock();
}
}

/**
* 记录锁释放
*/
public void recordLockRelease() {
monitorLock.lock();
try {
lockReleaseCount++;
} finally {
monitorLock.unlock();
}
}

/**
* 获取锁统计信息
*/
public LockStatistics getLockStatistics() {
monitorLock.lock();
try {
return LockStatistics.builder()
.acquireCount(lockAcquireCount)
.releaseCount(lockReleaseCount)
.averageWaitTime(lockAcquireCount > 0 ? lockWaitTime / lockAcquireCount : 0)
.isLocked(monitorLock.isLocked())
.queueLength(monitorLock.getQueueLength())
.build();
} finally {
monitorLock.unlock();
}
}

/**
* 锁统计信息
*/
@lombok.Data
@lombok.Builder
public static class LockStatistics {
private long acquireCount;
private long releaseCount;
private long averageWaitTime;
private boolean isLocked;
private int queueLength;
}
}

8. 控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package com.lock.controller;

import com.lock.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

/**
* ReentrantLock控制器
* @author Java实战
*/
@Slf4j
@RestController
@RequestMapping("/api/lock")
public class ReentrantLockController {

@Autowired
private BasicLockService basicLockService;

@Autowired
private ConditionService conditionService;

@Autowired
private ReadWriteLockService readWriteLockService;

@Autowired
private LockMonitorService lockMonitorService;

/**
* 使用非公平锁递增
*/
@PostMapping("/increment/unfair")
public ResponseEntity<String> incrementWithUnfairLock() {
try {
basicLockService.incrementWithUnfairLock();
return ResponseEntity.ok("非公平锁递增成功");
} catch (Exception e) {
log.error("非公平锁递增失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 使用公平锁递增
*/
@PostMapping("/increment/fair")
public ResponseEntity<String> incrementWithFairLock() {
try {
basicLockService.incrementWithFairLock();
return ResponseEntity.ok("公平锁递增成功");
} catch (Exception e) {
log.error("公平锁递增失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 尝试获取锁
*/
@PostMapping("/try-lock")
public ResponseEntity<Boolean> tryLock() {
try {
boolean success = basicLockService.tryIncrementWithLock();
return ResponseEntity.ok(success);
} catch (Exception e) {
log.error("尝试获取锁失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 超时获取锁
*/
@PostMapping("/timeout-lock")
public ResponseEntity<Boolean> timeoutLock(@RequestParam long timeout) {
try {
boolean success = basicLockService.incrementWithTimeoutLock(timeout, TimeUnit.MILLISECONDS);
return ResponseEntity.ok(success);
} catch (Exception e) {
log.error("超时获取锁失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 生产数据
*/
@PostMapping("/produce")
public ResponseEntity<String> produceData(@RequestParam int value) {
try {
conditionService.produceData(value);
return ResponseEntity.ok("数据生产成功: " + value);
} catch (Exception e) {
log.error("数据生产失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 消费数据
*/
@PostMapping("/consume")
public ResponseEntity<Integer> consumeData() {
try {
int data = conditionService.consumeData();
return ResponseEntity.ok(data);
} catch (Exception e) {
log.error("数据消费失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 读数据
*/
@GetMapping("/read")
public ResponseEntity<String> readData() {
try {
String data = readWriteLockService.readData();
return ResponseEntity.ok(data);
} catch (Exception e) {
log.error("读数据失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 写数据
*/
@PostMapping("/write")
public ResponseEntity<String> writeData(@RequestParam String data) {
try {
readWriteLockService.writeData(data);
return ResponseEntity.ok("数据写入成功: " + data);
} catch (Exception e) {
log.error("写数据失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 获取锁状态
*/
@GetMapping("/status")
public ResponseEntity<BasicLockService.LockStatus> getLockStatus() {
try {
BasicLockService.LockStatus status = basicLockService.getLockStatus();
return ResponseEntity.ok(status);
} catch (Exception e) {
log.error("获取锁状态失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 获取共享资源值
*/
@GetMapping("/resource")
public ResponseEntity<Integer> getSharedResource() {
try {
int value = basicLockService.getSharedResource();
return ResponseEntity.ok(value);
} catch (Exception e) {
log.error("获取共享资源失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 获取锁统计信息
*/
@GetMapping("/statistics")
public ResponseEntity<LockMonitorService.LockStatistics> getLockStatistics() {
try {
LockMonitorService.LockStatistics statistics = lockMonitorService.getLockStatistics();
return ResponseEntity.ok(statistics);
} catch (Exception e) {
log.error("获取锁统计信息失败", e);
return ResponseEntity.internalServerError().build();
}
}
}

9. 测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.lock.service;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
* ReentrantLock测试类
* @author Java实战
*/
@Slf4j
@SpringBootTest
public class ReentrantLockTest {

@Autowired
private BasicLockService basicLockService;

@Autowired
private ConditionService conditionService;

@Autowired
private ReadWriteLockService readWriteLockService;

/**
* 测试非公平锁
*/
@Test
public void testUnfairLock() throws InterruptedException {
log.info("开始测试非公平锁");

ExecutorService executor = Executors.newFixedThreadPool(5);
CountDownLatch latch = new CountDownLatch(10);

for (int i = 0; i < 10; i++) {
executor.submit(() -> {
try {
basicLockService.incrementWithUnfairLock();
} finally {
latch.countDown();
}
});
}

latch.await(30, TimeUnit.SECONDS);
executor.shutdown();

log.info("非公平锁测试完成,最终值: {}", basicLockService.getSharedResource());
}

/**
* 测试公平锁
*/
@Test
public void testFairLock() throws InterruptedException {
log.info("开始测试公平锁");

ExecutorService executor = Executors.newFixedThreadPool(5);
CountDownLatch latch = new CountDownLatch(10);

for (int i = 0; i < 10; i++) {
executor.submit(() -> {
try {
basicLockService.incrementWithFairLock();
} finally {
latch.countDown();
}
});
}

latch.await(30, TimeUnit.SECONDS);
executor.shutdown();

log.info("公平锁测试完成,最终值: {}", basicLockService.getSharedResource());
}

/**
* 测试条件变量
*/
@Test
public void testCondition() throws InterruptedException {
log.info("开始测试条件变量");

ExecutorService executor = Executors.newFixedThreadPool(2);

// 生产者线程
executor.submit(() -> {
for (int i = 1; i <= 5; i++) {
conditionService.produceData(i);
}
});

// 消费者线程
executor.submit(() -> {
for (int i = 1; i <= 5; i++) {
int data = conditionService.consumeData();
log.info("消费到数据: {}", data);
}
});

executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);

log.info("条件变量测试完成");
}

/**
* 测试读写锁
*/
@Test
public void testReadWriteLock() throws InterruptedException {
log.info("开始测试读写锁");

ExecutorService executor = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(15);

// 读线程
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
try {
String data = readWriteLockService.readData();
log.info("读取数据: {}", data);
} finally {
latch.countDown();
}
});
}

// 写线程
for (int i = 0; i < 5; i++) {
final int index = i;
executor.submit(() -> {
try {
readWriteLockService.writeData("数据" + index);
log.info("写入数据: 数据{}", index);
} finally {
latch.countDown();
}
});
}

latch.await(30, TimeUnit.SECONDS);
executor.shutdown();

log.info("读写锁测试完成");
}
}

10. 总结

ReentrantLock是Java并发编程中的重要工具。通过本文的详细介绍,我们了解了:

  1. 基础锁机制: 公平锁和非公平锁的使用
  2. 条件变量: 使用Condition实现线程等待和通知
  3. 读写锁: 使用ReadWriteLock提高读操作性能
  4. 锁监控: 监控锁的使用情况和性能
  5. 异常处理: 处理锁操作中的异常情况

通过合理使用ReentrantLock,可以为多线程应用提供可靠的同步机制。


Java实战要点:

  • ReentrantLock提供比synchronized更灵活的锁控制
  • 公平锁保证线程按请求顺序获取锁
  • Condition提供更精确的线程等待和通知机制
  • ReadWriteLock允许多个读操作并发执行
  • 合理使用锁避免死锁和性能问题

代码注解说明:

  • lock(): 获取锁,阻塞直到成功
  • tryLock(): 尝试获取锁,立即返回结果
  • tryLock(timeout, unit): 超时获取锁
  • lockInterruptibly(): 可中断获取锁
  • Condition.await(): 等待条件满足
  • Condition.signal(): 通知等待的线程