本文目录导读:

我来给你一个完整的Java读写锁(ReentrantReadWriteLock)案例,包含详细注释和易用场景。
基础案例:缓存示例
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 使用读写锁实现的缓存系统
* 特点:读读不互斥、读写互斥、写写互斥
*/
public class ReadWriteLockCache<K, V> {
private final Map<K, V> cache = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
// 写入数据(独占锁)
public void put(K key, V value) {
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在写入: " + key + "=" + value);
Thread.sleep(100); // 模拟耗时操作
cache.put(key, value);
System.out.println(Thread.currentThread().getName() + " 写入完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
}
// 读取数据(共享锁)
public V get(K key) {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 正在读取: " + key);
Thread.sleep(100); // 模拟耗时操作
V value = cache.get(key);
System.out.println(Thread.currentThread().getName() + " 读取完成: " + value);
return value;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
} finally {
lock.readLock().unlock();
}
}
// 测试代码
public static void main(String[] args) {
ReadWriteLockCache<String, String> cache = new ReadWriteLockCache<>();
// 多个写线程
for (int i = 0; i < 3; i++) {
final int index = i;
new Thread(() -> {
cache.put("key" + index, "value" + index);
}, "写线程-" + i).start();
}
// 多个读线程
for (int i = 0; i < 5; i++) {
final int index = i;
new Thread(() -> {
cache.get("key" + index);
}, "读线程-" + i).start();
}
}
}
读写锁降级示例
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 演示锁降级:写锁 -> 读锁
* 锁降级是指将写锁降级为读锁
*/
public class LockDowngradeDemo {
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private int data = 0;
private boolean updated = false;
/**
* 锁降级的正确使用:
* 1. 获取写锁
* 2. 获取读锁
* 3. 释放写锁
* 4. 释放读锁
*/
public void processData() {
rwLock.readLock().lock();
if (!updated) {
// 必须释放读锁才能获取写锁(锁升级不允许)
rwLock.readLock().unlock();
// 获取写锁
rwLock.writeLock().lock();
try {
// 再次检查状态(双重检查模式)
if (!updated) {
data = (int) (Math.random() * 100);
System.out.println(Thread.currentThread().getName()
+ " 更新数据为: " + data);
updated = true;
}
// 锁降级:在持有写锁的情况下获取读锁
rwLock.readLock().lock();
} finally {
// 释放写锁
rwLock.writeLock().unlock();
}
}
try {
// 此时持有读锁,可以安全读取
System.out.println(Thread.currentThread().getName()
+ " 读取数据: " + data);
} finally {
// 释放读锁
rwLock.readLock().unlock();
}
}
public static void main(String[] args) {
LockDowngradeDemo demo = new LockDowngradeDemo();
// 多个线程同时处理数据
for (int i = 0; i < 5; i++) {
new Thread(() -> {
demo.processData();
}, "线程-" + i).start();
}
}
}
公平与非公平模式对比
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class FairnessDemo {
public static void testFairness(boolean fair) {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
System.out.println("\n" + (fair ? "=== 公平模式 ===" : "=== 非公平模式 ==="));
// 创建多个写线程
Runnable writeTask = () -> {
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 获取写锁");
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " 释放写锁");
lock.writeLock().unlock();
}
};
// 创建多个读线程
Runnable readTask = () -> {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 获取读锁");
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " 释放读锁");
lock.readLock().unlock();
}
};
// 启动线程
Thread[] threads = new Thread[8];
for (int i = 0; i < 4; i++) {
threads[i * 2] = new Thread(readTask, "读线程-" + i);
threads[i * 2 + 1] = new Thread(writeTask, "写线程-" + i);
}
for (Thread t : threads) {
t.start();
}
// 等待所有线程完成
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 测试公平模式
testFairness(true);
// 测试非公平模式
testFairness(false);
}
}
实际业务场景:订单服务
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 订单服务:演示读写锁在真实业务中的应用
*/
public class OrderService {
// 订单数据库模拟
private static class Order {
String orderId;
String status;
double amount;
Order(String orderId, String status, double amount) {
this.orderId = orderId;
this.status = status;
this.amount = amount;
}
@Override
public String toString() {
return String.format("Order{id='%s', status='%s', amount=%.2f}",
orderId, status, amount);
}
}
private final Map<String, Order> orderDB = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock(true); // 公平锁
public OrderService() {
// 初始化一些订单
for (int i = 1; i <= 5; i++) {
orderDB.put("ORD" + i, new Order("ORD" + i, "已创建", 100.00 * i));
}
}
// 查询订单(读操作)
public Order getOrder(String orderId) {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ " 查询订单 " + orderId);
Thread.sleep(100);
return orderDB.get(orderId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} finally {
lock.readLock().unlock();
}
}
// 更新订单状态(写操作)
public boolean updateOrderStatus(String orderId, String newStatus) {
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ " 更新订单 " + orderId + " 状态为: " + newStatus);
Order order = orderDB.get(orderId);
if (order == null) {
return false;
}
Thread.sleep(200); // 模拟数据库更新操作
order.status = newStatus;
System.out.println(Thread.currentThread().getName()
+ " 订单更新成功");
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
lock.writeLock().unlock();
}
}
// 批量查询(读操作)
public void batchQuery() {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 开始批量查询");
orderDB.entrySet().stream()
.limit(3)
.forEach(e -> System.out.println(" " + e.getValue()));
Thread.sleep(200);
System.out.println(Thread.currentThread().getName() + " 批量查询完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.readLock().unlock();
}
}
public static void main(String[] args) {
OrderService service = new OrderService();
// 模拟订单处理场景
System.out.println("=== 订单处理系统启动 ===\n");
// 多个查询线程(读)
for (int i = 0; i < 4; i++) {
new Thread(() -> {
service.getOrder("ORD" + (1 + (int)(Math.random() * 5)));
service.batchQuery();
}, "查询线程-" + i).start();
}
// 多个更新线程(写)
for (int i = 0; i < 3; i++) {
new Thread(() -> {
service.updateOrderStatus("ORD" + (1 + (int)(Math.random() * 5)),
"已支付");
}, "更新线程-" + i).start();
}
}
}
读锁重入示例
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 展示读写锁的重入特性
*/
public class LockReentrantDemo {
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
public void readReentrant() {
rwl.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ " 第一次获取读锁");
// 读锁可以重入
rwl.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ " 第二次获取读锁(重入)");
} finally {
rwl.readLock().unlock();
System.out.println(Thread.currentThread().getName()
+ " 释放第二次读锁");
}
} finally {
rwl.readLock().unlock();
System.out.println(Thread.currentThread().getName()
+ " 释放第一次读锁");
}
}
public static void main(String[] args) {
LockReentrantDemo demo = new LockReentrantDemo();
// 多个线程测试读锁重入
for (int i = 0; i < 3; i++) {
new Thread(() -> {
demo.readReentrant();
}, "线程-" + i).start();
}
}
}
-
锁特性:
readLock():共享锁,允许多个线程同时读writeLock():独占锁,写时不允许读和写
-
锁降级:
- 写锁可以降级为读锁(持有写锁时获取读锁)
- 读锁不能升级为写锁(否则会死锁)
-
性能考量:
- 读多写少的场景使用读写锁性能较好
- 读少写多时,考虑普通锁或更高级的锁
-
注意事项:
- 读写锁非公平模式下,可防止写线程饿死
- 公平模式下,线程按请求顺序获取锁
- 释放锁时要放在finally块中
-
使用场景:
- 缓存系统
- 配置管理
- 订单系统
- 数据库连接池
- 任何读多写少的并发场景
这些示例涵盖了读写锁的主要使用场景和特性,你可以根据实际需求调整和使用。