读-写锁实现的加锁策略中,允许多个读操作同时进行,但每次只允许一个写操作。
ReentrantReadWriteLock
封装的 Map
示例
ReentrantReadWriteLock
在构造时可以选择是否为公平锁。
这里给出一个 ReentrantReadWriteLock
封装的 Map
的示例。
import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 使用ReentrantReadWriteLock封装的Map */ public class ReadWriteMap<K, V> { private final Map<K, V> map; // 当然我们也可以封装一些别的集合类 private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock r = lock.readLock(); private final Lock w = lock.writeLock(); public ReadWriteMap(Map<K, V> map) { this.map = map; } public V put(K key, V value) { w.lock(); System.out.println(Thread.currentThread() + " is putting."); // for debug try { return map.put(key, value); } finally { w.unlock(); } } public V get(Object key) { r.lock(); try { return map.get(key); } finally { r.unlock(); } } }
对 remove()
, putAll()
, clear()
等方法执行相同的操作。
测试代码
public class ReadWriteLockDemo { public static void main(String[] args) { final ReadWriteMap<String, String> map = new ReadWriteMap<>(new HashMap<>()); map.put("one", "init value"); for (int i = 1; i <= 4; i++) { new WorkThread(map).start(); } } // 模拟工作的线程 static class WorkThread extends Thread { private ReadWriteMap<String, String> map; public WorkThread(ReadWriteMap<String, String> map) { this.map = map; } @Override public void run() { for (int i = 1; i <= 2; i++) { try { System.out.println(this.toString() + " read out: " + map.get("one")); map.put("one", this.toString() + System.currentTimeMillis()); Thread.sleep(2); System.out.println(this.toString() + " read out: " + map.get("one")); } catch (InterruptedException e) { e.printStackTrace(); } } } } } /* 部分输出 Thread[main,5,main] is putting. Thread[Thread-1,5,main] read out: init value Thread[Thread-2,5,main] read out: init value Thread[Thread-1,5,main] is putting. Thread[Thread-2,5,main] is putting. Thread[Thread-3,5,main] read out: Thread[Thread-2,5,main]1536664817446 Thread[Thread-3,5,main] is putting. Thread[Thread-0,5,main] read out: Thread[Thread-3,5,main]1536664817446 Thread[Thread-0,5,main] is putting. Thread[Thread-2,5,main] read out: Thread[Thread-0,5,main]1536664817447 Thread[Thread-2,5,main] read out: Thread[Thread-0,5,main]1536664817447 Thread[Thread-3,5,main] read out: Thread[Thread-0,5,main]1536664817447 */
ReentrantLock不能完全替代synchronized,只有在synchronized无法满足需求时,才应该使用它。
读-写锁允许多个读线程并发地访问被保护的对象,当访问以读取操作为主的数据结构时,
它能提高程序的可伸缩性。