ReadWriteLock,读写锁。
ReentrantReadWriteLock 是 ReadWriteLock 的一种实现。
特点:
- 包含一个 ReadLock 和 一个 WriteLock 对象
- 读锁与读锁不互斥;读锁与写锁,写锁与写锁互斥
- 适合对共享资源有读和写操作,写操作很少,读操作频繁的场景
- 可以从写锁降级到读锁。获取写锁->获取读锁->释放写锁
- 无法从读锁升级到写锁
- 读写锁支持中断
- 写锁支持Condition;读锁不支持Condition
示例1–根据 key 获取 value 值
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;}
示例2–多线程环境下的读写锁使用
package constxiong.interview; import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 测试可重入 读写锁 * @author ConstXiong * @date 2019-06-10 11:19:42 */public class TestReentrantReadWriteLock {private Map<String, Object> map = new HashMap<String, Object>();private ReadWriteLock lock = new ReentrantReadWriteLock();/** * 根据 key 获取 value * @param key * @return */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 * @param key * @return */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) {final TestReentrantReadWriteLock test = new TestReentrantReadWriteLock();final String key = "lock";final Random r = new Random();for (int i = 0; i <5; i++) {new Thread(){@Overridepublic void run() {for (int j = 0; j <10; j++) {System.out.println(Thread.currentThread().getName() + " read value=" + test.get(key));}}}.start();new Thread(){@Overridepublic void run() {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();}}}