文章目录

  • 1.示例
  • 1.1 参与角色
  • 2 示例代码
  • 2.1 字段说明
  • 2.2 方法说明
  • 2.3 值得反复多读几次的代码
  • 总结



Read-Write Lock Pattern将读取与写入分开处理,在读取数据之前必须获取用来读取的锁定,而写入的时候必须获取用来写入的锁定。因为读取时实例的状态不会改变,所以多个线程可以同时读取;但是,写入会改变实例的状态,所以当有一个线程写入的时候,其它线程既不能读取与不能写入。


即读取与写入冲突 和 写入与写入冲突。

因为读取的线程之间没有冲突。因此多个Reader角色可以参与读取,提升程序性能。

1.示例

1.1 参与角色

Read-Write Lock模式的角色如下:

  • Reader(读取者)参与者
    Reader参与者会对SharedResource进行读。
  • Writer(写入者)参与者
    Writer参与者会对SharedResource进行写。
  • SharedResource(共享资源)参与者
    SharedResource代表Reader和Writer所共享的资源对象,SharedResource提供不改变内部状态的read操作,以及会改变内部状态的write操作。
  • ReadWriteLock(读写锁)参与者
    ReadWriteLock提供了对SharedResource参与者进行read操作和write操作时需要的锁定。

2 示例代码

2.1 字段说明

核心是这个实例。这个实例中定义了4个数量

• int readingReaders = 0; // 实际正在读取的线程数量
• int waitingWriters = 0; // 正在等待写入的线程数量
• int writingWriters = 0; // 实际正在写入的线程数量
• boolean preferWriter = true; // 写入优先的话,值为true

2.2 方法说明

  • readLock()方法
    只要preferWriter 为true,且有等待写的线程,读线程会wait。只要正在写,也会wait
  • readUnlock()方法
    每次readUnlock()后 就会将 preferWriter设置为true。
  • writeLock()方法
    只要有读线程、写线程在运行,就等待。
  • writeUnlock()方法
    将 preferWriter设置为False。

2.3 值得反复多读几次的代码

public final class ReadWriteLock {
    private int readingReaders = 0; // 实际正在读取的线程数量
    private int waitingWriters = 0; // 正在等待写入的线程数量
    private int writingWriters = 0; // (C)...实际正在写入的线程数量
    private boolean preferWriter = true; // 写入优先的话,值为true

    public synchronized void readLock() throws InterruptedException {
        while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
            wait();
        }
        readingReaders++;                       //  (A)实际正在读取的线程数量加1
    }

    public synchronized void readUnlock() {
        readingReaders--;                       //  (A)实际正在读取的线程数量减1
        preferWriter = true;  //read处理后优先处理write
        notifyAll();
    }

    public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;                       // (B)正在等待写入的线程数量加1
        try {
            while (readingReaders > 0 || writingWriters > 0) {
                wait();
            }
        } finally {
          waitingWriters--;                   // (B)正在等待写入的线程数量减1
        }
        writingWriters++;                       //  (C)实际正在写入的线程数量加1
    }

    public synchronized void writeUnlock() {
        writingWriters--;                       // (C)实际正在写入的线程数量减
        preferWriter = false;  //write处理后优先处理read
        notifyAll();
    }
}



总结

Read-Write Lock 模式适用于读取频率比写入频率高的场景。
Read-Write Lock Pattern将读取与写入分开处理,在读取数据之前必须获取用来读取的锁定,而写入的时候必须获取用来写入的锁定。因为读取时实例的状态不会改变,所以多个线程可以同时读取;但是,写入会改变实例的状态,所以当有一个线程写入的时候,其它线程既不能读取与不能写入。