介绍

读写锁,允许多个线程同时读共享资源,但只允许一个线程写共享资源。适合读多写少的高并发环境

使用

用读写锁实现一个在高并发环境下线程安全的缓存

  1. package cn.zjm404.stu.thread.lock.rw;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReadWriteLock;
  6. import java.util.concurrent.locks.ReentrantReadWriteLock;
  7. public class MyCache<K,V> {
  8. private final Map<K,V> cache = new HashMap<>();
  9. private final ReadWriteLock rwl = new ReentrantReadWriteLock();
  10. private final Lock r = rwl.readLock();
  11. private final Lock w = rwl.writeLock();
  12. /**
  13. * 读缓存
  14. * @param key
  15. * @return 查询到的数据
  16. */
  17. public V get(K key){
  18. //上读锁
  19. r.lock();
  20. try{
  21. return cache.get(key);
  22. }finally {
  23. //释放读锁
  24. r.unlock();
  25. }
  26. }
  27. /**
  28. * 写缓存
  29. * @param key
  30. * @param value
  31. */
  32. public void put(K key,V value){
  33. //获取写锁
  34. w.lock();
  35. try{
  36. cache.put(key,value);
  37. }finally {
  38. //释放写锁
  39. w.unlock();
  40. }
  41. }
  42. }

锁的升降级

锁的升级(不支持)

读写锁并不支持从读锁升级为写锁,当进行锁升级时,并发环境下会产生死锁。举个例子,代码如下
image.png

  • 设在某一时刻,有两个线程 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(); } } }

```