java面试题-说一说ReadWriteLock如何使用?
简介
在多线程编程中,读写锁是一种重要的同步机制,用于提高对共享资源的访问效率。Java中的ReentrantReadWriteLock
是ReadWriteLock
接口的一种实现,提供了对共享资源进行读写操作的灵活性。
特点
- 读锁与读锁不互斥
- 读锁与写锁互斥
- 支持写锁降级到读锁
- 无法从读锁升级到写锁
- 支持中断
- 写锁支持Condition,读锁不支持Condition
基本使用
首先,我们来看一个简单的示例,根据给定的key
获取对应的value
。在这个过程中,我们会使用ReentrantReadWriteLock
的基本结构。
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample {
private ReadWriteLock lock = new ReentrantReadWriteLock();
// 根据 key 获取 value 值
public Object getValue(String key) {
lock.readLock().lock(); // 加读锁
Object value = null;
try {
value = cache.get(key);
if (value == null) {
lock.readLock().unlock(); // value值为空,释放读锁
lock.writeLock().lock(); // 加写锁,写入value值
try {
// 重新检查 value值是否已经被其他线程写入
if (value == null) {
value = "value"; // 写入数据
}
} finally {
lock.writeLock().unlock();
}
lock.readLock().lock();
}
} finally {
lock.readLock().unlock();
}
return value;
}
}
这个例子展示了如何利用读写锁实现对共享资源的读写操作,确保写入操作不会被多个线程同时执行,而读取操作可以并发进行。
多线程环境下的读写锁使用
下面我们将介绍一个更复杂的例子,展示在多线程环境下如何使用可重入读写锁。我们创建一个包含读写锁的类,用于存储键值对。
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReentrantReadWriteLockDemo {
// 存储 key value 的 map
private Map<String, Object> map = new HashMap<>();
// 读写锁
private final ReadWriteLock lock = new ReentrantReadWriteLock();
// 根据 key 获取 value
public Object get(String key) {
Object value = null;
lock.readLock().lock();
try {
Thread.sleep(50L);
value = map.get(key);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
}
return value;
}
// 设置 key-value
public void set(String key, Object value) {
lock.writeLock().lock();
try {
Thread.sleep(50L);
map.put(key, value);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
}
// 测试5个线程读数据,5个线程写数据
public static void main(String[] args) {
// 创建测试可重入读写锁对象
ReentrantReadWriteLockDemo test = new ReentrantReadWriteLockDemo();
String key = "lock"; // 存入 map 中的 key
Random r = new Random(); // 生成随机数作为 value
// 5 个线程读 map 中 key 的 value
for (int i = 0; i < 5; i++) {
new Thread(() -> {
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " read value=" + test.get(key));
}
}).start();
// 5 个线程写 map 中 key 的 value
new Thread(() -> {
for (int j = 0; j < 10; j++) {
int value = r.nextInt(1000);
test.set(key, value);
System.out.println(Thread.currentThread().getName() + " write value=" + value);
}
}).start();
}
}
}
这个例子展示了如何在多线程环境下安全地进行读写操作,确保线程安全性。
正文到此结束
- 本文标签: Java 面试题
- 本文链接: https://www.jietongc.com/article/89
- 版权声明: 本文由大熊科技原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权