在Read-Write Lock模式中,读取操作和写入操作是分开考虑的。在执行读取操作之前,线程必须获取用于读取的锁。而在执行写入操作之前,线程必须获取用于写入的锁。
由于当线程执行读取操作时,实例的状态不会发生变化,所以多个线程可以同时读取。但在读取时,不可以写入。
当线程执行写入操作时,实例的状态就会发生变化。因此,当有一个线程正在写入时,其他线程不可以读取或写入。
一般来说,执行互斥处理会降低程序性能。但如果把针对写入的互斥处理和针对读取的互斥处理分开来考虑,则可以提高程序性能。
示例
多个线程对Data类的实例执行读写操作。
类图
Main.java
1 | public class Main { |
Data.java
1 | public class Data { |
WriterThread.java
1 | import java.util.Random; |
ReaderThread.java
1 | public class ReaderThread extends Thread { |
ReadWriteLock.java
为了确保安全性,必须防止如下两种冲突。
- “读取”和“写入”的冲突(read-write conflict)
- “写入”和“写入”的冲突(write-write conflict)
当线程想要获取用于读取的锁时:
- 如果有线程正在执行写入,则等待。否则,会引起read-write conflict。
- 如果有线程正在执行读取,则无需等待。read-read不会引起conflict。
当线程想要获取用于写入的锁时:
- 如果有线程正在执行写入,则等待。否则,会引起write-write conflict。
- 如果有线程正在执行读取,则等待。否则,会引起read-write conflict。
1 | public final class ReadWriteLock { |
运行结果
1 | Thread-0 reads ********** |
登场角色
Reader(读者)
Reader角色对SharedResource角色执行read操作。在示例程序中,由ReaderThread类扮演此角色。
Writer(写者)
Writer角色对SharedResource角色执行write操作。在示例程序中,由WriterThread类扮演此角色。
SharedResource(共享资源)
SharedResource角色表示的是Reader角色和Writer角色二者共享的资源。SharedResource角色提供不修改内部状态的操作(read)和修改内部状态的操作(write)。在示例程序中,由Data类扮演此角色。
ReadWriteLock(读写锁)
ReadWriteLock角色提供了SharedResource角色实现read操作和write操作时所需的锁。即实现read操作时所需的readLock和readUnlock,以及实现write操作时所需的writeLock和writeUnlock。在示例程序中,由ReadWriteLock类扮演此角色。