感谢:多线程基础总结八--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;
}
}
}
}