难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJIDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.温故知新
前面在《“全栈2019”Java多线程第四十章:ReadWriteLock读写锁》一章中介绍了读写锁ReadWriteLock。
在《“全栈2019”Java多线程第四十一章:读锁与写锁之间相互嵌套例子》一章中介绍了读锁与写锁之间相互嵌套情况。
在《“全栈2019”Java多线程第四十二章:获取线程与读写锁的保持数》一章中介绍了可重入读写锁ReentrantReadWriteLock的获取线程与读写锁保持数系列方法。
在《“全栈2019”Java多线程第四十三章:查询是否有线程在等待读写锁》一章中介绍了可重入读写锁ReentrantReadWriteLock的查询是否有线程正在等待获取读写锁hasQueuedThreads()方法、获取有多少个正在等待获取读写锁的线程getQueueLength()方法和查询指定线程是否正在等待获取读写锁的hasQueuedThread(Thread thread)方法。
现在介绍可重入读写锁ReentrantReadWriteLock与Condition的关系,在读写锁中,写锁是支持Condition的,读锁是不支持Condition的,原因在于写锁在某一时刻最多只能被一个线程拥有,而读锁在某一时刻最多可以被多个线程拥有,对于读锁而言,其他线程没有必要等待获取读锁,等待唤醒是毫无意义的。
2.写锁支持Condition
读写锁中,只有写锁支持Condition,下面通过程序来验证。
首先,创建出读写锁:
其次,创建出读锁与写锁:
再者,创建两个线程,并重写run()方法:
先来启动线程,再完善run()方法:
在run()方法里面获取写锁:
然后,我们需要在一个线程里面进行等待另一个线程里面将其唤醒。
所以,需要创建出写锁的Condition对象:
在thread1线程里面调用Condition对象的await()方法使线程等待:
并在等待的前后各输出一句话,目的是为了记录线程如何被等待以及何时被唤醒:
在thread2线程里面调用Condition对象的signal()/signalAll()方法唤醒被等待的线程:
最后,我们需要先启动thread1线程,再过3秒钟启动thread2线程,所以要使主线程睡3秒钟:
例子书写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。thread1线程被等待,过了3秒钟之后才醒来。
这个也说明了写锁是支持Condition的。
3.读锁不支持Condition
但是,与写锁不同的是,读锁不支持Condition。
还是上一小节的例子,通过读锁对象来获取读锁的Condition对象:
其实,这样做已经够了,不必再往下改写了,看运行结果大家就知道了。
运行程序,执行结果:
静图:
文字版:
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.UnsupportedOperationException
\tat java.base/java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.newCondition(ReentrantReadWriteLock.java:907)
\tat main.Main.<clinit>(Main.java:31)
从运行结果来看,程序发生了UnsupportedOperationException异常。
UnsupportedOperationException是什么异常?
UnsupportedOperationException叫“不支持的操作异常”。
不支持什么操作?
在此处是读锁不支持Condition的意思,操作指的是获取Condition。
另外,我们还可以通过ReentrantReadWriteLock.ReadLock内部类中的newCondition()方法源码得知读锁是不支持Condition的:
将注释翻译成中文:
可以看到newCondition()方法始终抛出UnsupportedOperationException异常。
今日说这个就是想提醒大家,避免大家日常开发中或者面试时弄错。
最后,希望大家可以把这个例子照着写一遍,然后再自己默写一遍,方便以后碰到类似的面试题可以轻松应对。
祝大家编码愉快!
GitHub
本章程序GitHub地址:https://github.com/gorhaf/Java2019/tree/master/Thread/ReadWriteLock/ReentrantReadWriteLock
总结
- 写锁支持Condition。
- 读锁不支持Condition。
- 在读写锁中,写锁是支持Condition的,读锁是不支持Condition的,原因在于写锁在某一时刻最多只能被一个线程拥有,而读锁在某一时刻最多可以被多个线程拥有,对于读锁而言,其他线程没有必要等待获取读锁,等待唤醒是毫无意义的。
至此,Java中读写锁与Condition的支持情况相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
“全栈2019”Java多线程第四十三章:查询是否有线程在等待读写锁
下一章
“全栈2019”Java多线程第四十五章:查询Condition上等待线程个数
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!
- 上一篇:沃尔沃终于忍不住了?XC60最高降8万,白菜价也没人要-xc60
- 下一篇:没有了