ReentrantReadWriteLock可重入读写锁
1.可重入读写锁的浅析
简单使用
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
private static final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
public static void main(String[] args) {
Thread t1 = new Thread(BB::read,"t1");
Thread t2 = new Thread(BB::write,"t2");
Thread t3 = new Thread(BB::write,"t3");
Thread t4 = new Thread(BB::read,"t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
public static void read(){
String name = Thread.currentThread().getName();
System.out.println(name+"线程进入read方法");
readLock.lock();
System.out.println(name+"线程===持有read锁");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"线程===准备解read锁");
readLock.unlock();
}
public static void write(){
String name = Thread.currentThread().getName();
System.out.println(name+"线程进入write方法");
writeLock.lock();
System.out.println(name+"线程===持有write锁");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"线程===准备解write锁");
writeLock.unlock();
}
可能出现的结果1:
t1线程进入read方法
t4线程进入read方法
t1线程===持有read锁
t3线程进入write方法
t2线程进入write方法
t4线程===持有read锁
t4线程===准备解read锁
t1线程===准备解read锁
t2线程===持有write锁
t2线程===准备解write锁
t3线程===持有write锁
t3线程===准备解write锁
可能出现的结果2:
t1线程进入read方法
t4线程进入read方法
t2线程进入write方法
t3线程进入write方法
t1线程===持有read锁
t4线程===持有read锁
t4线程===准备解read锁
t1线程===准备解read锁
t3线程===持有write锁
t3线程===准备解write锁
t2线程===持有write锁
t2线程===准备解write锁
可能出现的结果3:
t2线程进入write方法
t4线程进入read方法
t3线程进入write方法
t1线程进入read方法
t2线程===持有write锁
t2线程===准备解write锁
t4线程===持有read锁
t4线程===准备解read锁
t3线程===持有write锁
t3线程===准备解write锁
t1线程===持有read锁
t1线程===准备解read锁
- 从结果可以分析出来可重入读写锁的规则是:并发的时候,读读共享,读写互斥,写写互斥
- 读读共享:假设第一个进来的线程持有了读锁,尽在进行读操作,接着又来一个线程是读操作,那么第二个线程依旧可以持有读锁,共享这份被读锁锁定的代码部分,如果第二个是写操作就会等待,直到第一个线程读完,其它的以此类推。
可重入读写锁的应用:实现一个简单缓存,应对并发问题
**
* 简单缓存,无超时实现,使用{@link WeakHashMap}实现缓存自动清理
* @author Looly
*
* @param <K> 键类型
* @param <V> 值类型
*/
public class SimpleCache<K, V> implements Serializable{
private static final long serialVersionUID = 1L;
private final Map<K, V> cache = new WeakHashMap<>();
private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
private final ReadLock readLock = cacheLock.readLock();
private final WriteLock writeLock = cacheLock.writeLock();
public V get(K key) {
readLock.lock();
V value;
try {
value = cache.get(key);
} finally {
readLock.unlock();
}
return value;
}
public V put(K key, V value){
writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
return value;
}
public V remove(K key) {
writeLock.lock();
try {
return cache.remove(key);
} finally {
writeLock.unlock();
}
}
public void clear() {
writeLock.lock();
try {
this.cache.clear();
} finally {
writeLock.unlock();
}
}
}