Skip to content

读写锁

一个资源可以被多个读操作访问,或者被一个写操作访问,但是不能同时存在多个写操作(读写互斥,写写互斥)

  • 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();
    }
}