Appearance
读写锁
一个资源可以被多个读操作访问,或者被一个写操作访问,但是不能同时存在多个写操作(读写互斥,写写互斥)
- ReentrantReadWriteLock 是读写锁的实现类
读写锁的缺点:
- 读写锁的实现是基于AQS的,所以读写锁的实现是比较复杂的,性能也不如synchronized
- 造成锁饥饿问题,写锁的优先级高于读锁,如果读锁的线程很多,写锁的线程很少,那么写锁的线程可能一直获取不到锁,导致锁饥饿问题
- 读的时候不能写,写的时候可以读,但是要合并.
锁降级
- 锁降级是指将写锁降级为读锁
- 锁降级的目的是为了避免死锁
- 锁降级的过程是先获取写锁,然后获取读锁,再释放写锁,再释放读锁.
一个演示锁降级的例子:
java
public class LockDowngrade {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
private ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
public void read() {
readLock.lock();
System.out.println(Thread.currentThread().getName() + " 获取读锁");
writeLock.lock();
System.out.println(Thread.currentThread().getName() + " 获取写锁");
writeLock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放写锁");
readLock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放读锁");
}
public void write() {
writeLock.lock();
System.out.println(Thread.currentThread().getName() + " 获取写锁");
readLock.lock();
System.out.println(Thread.currentThread().getName() + " 获取读锁");
readLock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放读锁");
writeLock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放写锁");
}
public static void main(String[] args) {
LockDowngrade lockDowngrade = new LockDowngrade();
new Thread(() -> lockDowngrade.read(), "Thread-1").start();
new Thread(() -> lockDowngrade.write(), "Thread-2").start();
}
}