JUC中的读写锁(ReentrantReadWriteLock)
Posted XeonYu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC中的读写锁(ReentrantReadWriteLock)相关的知识,希望对你有一定的参考价值。
上一篇:
JUC中的线程通信 Condition
ReentrantReadWriteLock
在之前的文章中,我们已经介绍了ReadWriteLock 接口
JUC已经给我们提供了一个该接口的实现类,就是ReentrantReadWriteLock(可重入读写锁)
看一下读写锁跟普通锁的区别:
- 读写锁维护了两把锁,分别是读锁和写锁
- 读写锁中的读锁可以同时被多个线程同时持有,写锁跟普通锁一样,同一时间只能被一个线程持有,读锁和写锁会相互排斥,属于悲观锁
下面我们来看个示例:
/*普通的可重入锁*/
class ReentranLockDemo {
private final ReentrantLock reentrantLock = new ReentrantLock();
private int num = 0;
public void write() {
reentrantLock.lock();
try {
TimeUnit.MILLISECONDS.sleep(500);
num++;
System.out.println("write num = " + num);
} catch (Exception e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
public void read() {
reentrantLock.lock();
try {
TimeUnit.MILLISECONDS.sleep(500);
System.out.println("\\"read\\"+num = " + num);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("reentrantLock.getHoldCount() = " + reentrantLock.getHoldCount());
reentrantLock.unlock();
}
}
}
我们用了一个ReentrantLock 分别锁住read和write方法。
main方法代码如下:
public static void main(String[] args) {
ReentranLockDemo reentranLockDemo = new ReentranLockDemo();
/*起10个线程执行read方法*/
for (int i = 0; i < 10; i++) {
new Thread(reentranLockDemo::read).start();
}
/*起10个线程执行write方法*/
for (int i = 0; i < 10; i++) {
new Thread(reentranLockDemo::write).start();
}
}
看下执行结果:
运行结果如上,符合预期。
下面我们将ReentrantLock换成ReentrantReadWriteLock 试一下:
/*读写锁*/
class ReadWriteLockDemo {
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private int num = 0;
public void write() {
readWriteLock.writeLock().lock();
try {
TimeUnit.MILLISECONDS.sleep(500);
num++;
System.out.println("write num = " + num);
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
public void read() {
readWriteLock.readLock().lock();
try {
TimeUnit.MILLISECONDS.sleep(500);
System.out.println("\\"read\\"+num = " + num);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("readWriteLock.getReadLockCount() = " + readWriteLock.getReadLockCount());
readWriteLock.readLock().unlock();
}
}
}
main方法如下:
public static void main(String[] args) {
ReadWriteLockDemo readWriteLockDemo = new ReadWriteLockDemo();
/*起10个线程执行read方法*/
for (int i = 0; i < 10; i++) {
new Thread(readWriteLockDemo::read).start();
}
/*起10个线程执行write方法*/
for (int i = 0; i < 10; i++) {
new Thread(readWriteLockDemo::write).start();
}
}
运行结果:
可以看到,读写锁在多线程读的情况下,ReentrantReadWriteLock执行速度明显比ReentrantLock快,而且可以看到ReentrantLock同一时间只会被一个线程持有,而ReentrantReadWriteLock中的读锁可以同时被多个线程持有。
其中读锁和写锁是互斥的,也就是说假如线程持有了读锁,那么获取写锁的线程会被阻塞,同样的,假如写锁被其它线程持有,那么获取读锁的线程就会被阻塞。因此,ReentrantReadWriteLock是一种悲观锁
这就是读写锁为什么在读的时候会比普通锁执行效率的高的原因。
所以,读写锁非常适合用在 读多写少的同步操作中。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
以上是关于JUC中的读写锁(ReentrantReadWriteLock)的主要内容,如果未能解决你的问题,请参考以下文章
JUC中的读写锁(ReentrantReadWriteLock)
JUC并发编程 共享模式之工具 JUC 读写锁 ReentrantReadWriteLock -- ReentrantReadWriteLock(不可重入锁)使用 & 注意事项