介绍
读写锁,允许多个线程同时读共享资源,但只允许一个线程写共享资源。适合读多写少的高并发环境
使用
用读写锁实现一个在高并发环境下线程安全的缓存
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(); } } }
```
