介绍
读写锁,允许多个线程同时读共享资源,但只允许一个线程写共享资源。适合读多写少的高并发环境
使用
用读写锁实现一个在高并发环境下线程安全的缓存
package cn.zjm404.stu.thread.lock.rw;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyCache<K,V> {
private final Map<K,V> cache = new HashMap<>();
private final ReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
/**
* 读缓存
* @param key
* @return 查询到的数据
*/
public V get(K key){
//上读锁
r.lock();
try{
return cache.get(key);
}finally {
//释放读锁
r.unlock();
}
}
/**
* 写缓存
* @param key
* @param value
*/
public void put(K key,V value){
//获取写锁
w.lock();
try{
cache.put(key,value);
}finally {
//释放写锁
w.unlock();
}
}
}
锁的升降级
锁的升级(不支持)
读写锁并不支持从读锁升级为写锁,当进行锁升级时,并发环境下会产生死锁。举个例子,代码如下
- 设在某一时刻,有两个线程 t1 , t2 ,都已获取了 demo 中的读锁
- t1尝试获取写锁,但是写锁为排他锁,需要等待 t2 释放读锁后才可以获取
- 此时,t2 进行到了 w.lock() 尝试获取写锁,同理,需要等待 t1 释放读锁后才可以获取
锁的降级
```java package cn.zjm404.stu.thread.lock.rw;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DowngradeLock { private final ReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); private String msg; public void demo(){ r.lock(); try{ //msg 为 null ,释放读锁,获取写锁,进行写入 if(msg == null){ r.unlock(); w.lock(); try{ //二次判断,看是否有线程更新过了 if(msg != null){ System.out.println(msg); return; } msg = “hello world”; //锁降级 r.lock(); }finally { w.unlock(); } } System.out.println(“msg”); }finally { //释放读锁 r.unlock(); } } }
```