Java的ReentrantReadWriteLock 类
Java 的ReentrantReadWriteLock类是 ReadWriteLock 的一个实现,它也支持 ReentrantLock 功能。
ReadWriteLock 是一对关联的锁,一个用于只读操作,一个用于写入。而 ReentrantLock 是一种可重入互斥锁,其行为与使用同步方法和语句访问的隐式监视器锁相同,但具有更多扩展功能。
Java的读写锁
即使在多线程应用程序中,对于共享资源也可以同时进行多次读取。只有当多个写入同时发生或读写混合时,才有可能写入错误值或读取错误值。
Java的ReadWriteLock 使用相同的思想,通过单独的一对锁来提高性能。一个 ReadWriteLock 维护着一对关联的锁——
- 一种用于只读操作;和
- 一种用于写作。
只要没有写者,读锁就可以被多个读者线程同时持有。写锁是独占的。
拥有一对读写锁允许在访问共享数据时比互斥锁允许的并发级别更高。它利用了这样一个事实,即虽然一次只有一个线程(写入线程)可以修改共享数据,但在许多情况下,任意数量的线程都可以同时读取数据(因此是读取线程)。
如果读的频率多于写,读操作的持续时间多于写的持续时间,读写锁将比使用互斥锁提高性能。它还取决于对数据的争用——即尝试同时读取或写入数据的线程数。
包资源管理器视图
• java.lang.Object
• java.util.concurrent.locks.ReentrantReadWriteLock
语法:导入类
public class ReentrantReadWriteLock
extends Object
implements ReadWriteLock, Serializable
构造函数总结
- ReentrantReadWriteLock():创建一个具有默认(非公平)排序属性的新 ReentrantReadWriteLock。
- ReentrantReadWriteLock(boolean fair):使用给定的公平策略创建一个新的 ReentrantReadWriteLock。
抛出异常:
- NullPointerException: 如果锁为空
执行:
我们将创建三个 Runnable 实现。它们都使用 ReentrantReadWriteLock 锁变量。该锁是使用 ReentrantReadWriteLock(boolean fair) 构造函数创建的,因此它被赋予了一个公平策略:
- 读得到锁。它使用 ReentrantReadWriteLock 的 readLock() API 方法来获取 ReadLock。然后,它使用 ReadLock 的 lock() 方法获取读锁。拥有锁时,它读取字符串消息变量的值。然后它尝试使用 ReadLock 的 unlock() 方法释放锁。
- WriteA 和 WriteB 也获得锁,使用 writeLock() 方法,返回一个 WriteLock,然后使用 WriteLock 的 unlock() 方法。由于拥有写锁,它们都改变了 String 消息变量的值。然后,他们使用 WriteLock 的 unlock() 方法释放写锁。
例子
Java
// Java Program to Illustrate ReentrantReadWriteLock Class
// Importing ReentrantReadWriteLock
// fro java.util package
import java.util.concurrent.locks.ReentrantReadWriteLock;
// Class 1
// Main class
public class ReentrantReadWriteLockExample {
private static final ReentrantReadWriteLock lock
= new ReentrantReadWriteLock(true);
// Initially the string contains only 1 character
private static String message = "a";
// Main driver method
public static void main(String[] args)
throws InterruptedException
{
// Creating threads
Thread t1 = new Thread(new Read());
Thread t2 = new Thread(new WriteA());
Thread t3 = new Thread(new WriteB());
// Starting threads with help of start() method
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
// Class 2
// Helper class implementig Runnable interface
static class Read implements Runnable {
// run() method for thread
public void run()
{
for (int i = 0; i <= 10; i++) {
if (lock.isWriteLocked()) {
System.out.println(
"I'll take the lock from Write");
}
// operating lock()
lock.readLock().lock();
System.out.println(
"ReadThread "
+ Thread.currentThread().getId()
+ "Message is " + message);
lock.readLock().unlock();
}
}
}
// Class 3
// Helper class implementig Runnable interface
static class WriteA implements Runnable {
// run() method for thread
public void run()
{
for (int i = 0; i <= 10; i++) {
// Try block to check fr exceptions
try {
lock.writeLock().lock();
message = message.concat("a");
}
finally {
lock.writeLock().unlock();
}
}
}
}
// Class 4
// Helper class implementig Runnable interface
static class WriteB implements Runnable {
// run() method for thread
public void run()
{
for (int i = 0; i <= 10; i++) {
// Try block to check for exceptions
try {
lock.writeLock().lock();
message = message.concat("b");
}
finally {
lock.writeLock().unlock();
}
}
}
}
}
ReadThread 11 ---> Message is a
ReadThread 11 ---> Message is aba
ReadThread 11 ---> Message is ababa
ReadThread 11 ---> Message is abababa
ReadThread 11 ---> Message is ababababa
ReadThread 11 ---> Message is abababababa
ReadThread 11 ---> Message is ababababababa
ReadThread 11 ---> Message is abababababababa
ReadThread 11 ---> Message is ababababababababa
ReadThread 11 ---> Message is abababababababababa
ReadThread 11 ---> Message is ababababababababababa