ReadWriteLock
ReadWriteLock是JDK5中提供的读写分离锁。读写分离锁可以有效地帮助减少锁竞争,以提高系统性能。用锁分离的机制来提升性能非常容易理解,比如线程A1,A2,A3进行写操作,B1,B2,B3进行读操作,如果使用重入锁或者内部锁(synchronized)则论路上说所有读之间、读与写之间、写与写之间都是穿行操作的。当B1进行读取时,B2、B3则需要等待锁。由于读操作并不对数据的完整性造成破坏,这种等待显然是不合理的。因此,读写锁就有了发挥功能的余地。
在这种情况下,读写锁允许多个线程同时读,使得B1,B2,B3之间真正并行。但是,考虑都数据完整性,写写操作和读写操作间依然时需要相互等待和持有锁的。总的来说,读写锁的访问约束如下表:
使用示例
如果在系统中,读操作次数远远大于写操作,则读写锁就可以发挥最大的功效,提升系统的性能。这里我给出一个稍微夸张点的案例,来说明读写锁对性能的帮助:
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-5-4 0004 9:17
* @Description: 读写锁案例
*/
public class ReadWriteLockDemo {
private static Lock lock = new ReentrantLock();
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock();
private int val;
/**
* 处理读操作
*
* @throws InterruptedException
*/
public Object handleRead(Lock lock) throws InterruptedException {
try {
// 模拟读操作
lock.lock();
// 读操作的耗时越多,读写锁的性能优势就越明显
Thread.sleep(1000);
return val;
} finally {
lock.unlock();
}
}
/**
* 处理写操作
*
* @throws InterruptedException
*/
public void handleWrite(Lock lock, int index) throws InterruptedException {
try {
// 模拟写操作
lock.lock();
Thread.sleep(1000);
val = index;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
final ReadWriteLockDemo demo = new ReadWriteLockDemo();
Runnable readRunnale = new Runnable() {
@Override
public void run() {
try {
demo.handleRead(readLock);
demo.handleRead(lock);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable writeRunnable = new Runnable() {
@Override
public void run() {
try {
demo.handleWrite(writeLock, new Random().nextInt());
demo.handleWrite(lock, new Random().nextInt());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for (int i=0; i<18; i++){
new Thread(readRunnale).start();
}
for (int i=0; i<2; i++){
new Thread(writeRunnable).start();
}
}
}
总结
对于读写锁访问约束如下:
(1)读-读不互斥:读读之间不阻塞
(2)读-写互斥:读阻塞写,写也会阻塞读
(3)写-写互斥:写写阻塞