感谢:多线程基础总结八--ReentrantReadWriteLock
ReentReadWriteLock // 可重入的读/写锁
- 它和ReentrantLock都是单独的实现,不存在继承,实现的关系!
- 它分读锁 和 写锁两部分!readLock() 和 writeLock()
- 多个线程可以同时对一块资源进行读!但是,这是就不能进行写了!排斥写 ,因为读锁,并不涉及对资源的修改,也就不存在线程安全的问题!
- 然而,写锁间却是互斥的!一个写锁套在某块资源上,别的线程就不能再读或写了! 读-读能共存,读-写不能共存,写-写不能共存
- 重入方面,得到写锁后还可以再得到读锁!但是,读到读锁,你就不能再得到写锁了!
- 锁降级 : 获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author: yanxuxin * @date: 2010-1-7 */ public class ReentrantReadWriteLockSample { public static void main(String[] args) { testReadLock(); // testWriteLock(); } // 多线程的答案 说不准 public static void testReadLock() { final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport(); support.initCache(); Runnable runnable = new Runnable() { public void run() { support.get("test"); } }; // 这两个是读操作,可以同时进行,不会被阻塞 new Thread(runnable).start(); new Thread(runnable).start(); // 这个是写操作,必须等到读锁释放才能写 new Thread(new Runnable() { public void run() { support.put("test", "test"); } }).start(); } public static void testWriteLock() { final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport(); support.initCache(); // 两个写操作不能同时进行 ,在写的时候不能在读 new Thread(new Runnable() { public void run() { support.put("key1", "value1"); } }).start(); new Thread(new Runnable() { public void run() { support.put("key2", "value2"); } }).start(); new Thread(new Runnable() { public void run() { support.get("key1"); } }).start(); } } class ReadWriteLockSampleSupport { private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); private volatile boolean completed; private Map<String,String> cache; public void initCache() { readLock.lock(); if(!completed) { // Must release read lock before acquiring write lock readLock.unlock(); // (1) // 读写锁的重入问题 writeLock.lock(); // (2) if(!completed) { cache = new HashMap<String,String>(32); completed = true; } // Downgrade by acquiring read lock before releasing write lock readLock.lock(); // (3) writeLock.unlock(); // (4) Unlock write, still hold read 锁降级 } System.out.println("empty? " + cache.isEmpty()); readLock.unlock(); } public String get(String key) { readLock.lock(); System.out.println(Thread.currentThread().getName() + " read."); startTheCountdown(); try{ return cache.get(key); } finally{ readLock.unlock(); } } public String put(String key, String value) { writeLock.lock(); System.out.println(Thread.currentThread().getName() + " write."); startTheCountdown(); try{ return cache.put(key, value); } finally { writeLock.unlock(); } } /** * A simple countdown,it will stop after about 5s. */ public void startTheCountdown() { long currentTime = System.currentTimeMillis(); for(;;) { long diff = System.currentTimeMillis() - currentTime; if(diff > 5000) { break; } } } }