难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJIDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.温故知新
前面在 一章中介绍了读写锁ReadWriteLock。
在 一章中介绍了读锁与写锁之间相互嵌套情况。
在 一章中介绍了可重入读写锁ReentrantReadWriteLock的获取线程与读写锁保持数系列方法。
在 一章中介绍了可重入读写锁ReentrantReadWriteLock的查询是否有线程正在等待获取读写锁hasQueuedThreads()方法、获取有多少个正在等待获取读写锁的线程getQueueLength()方法和查询指定线程是否正在等待获取读写锁的hasQueuedThread(Thread thread)方法。
在 一章中介绍了可重入读写锁ReentrantReadWriteLock与Condition的关系,在读写锁中,写锁是支持Condition的,读锁是不支持Condition的,原因在于写锁在某一时刻最多只能被一个线程拥有,而读锁在某一时刻最多可以被多个线程拥有,对于读锁而言,其他线程没有必要等待获取读锁,等待唤醒是毫无意义的。
在 一章中介绍了如何查询Condition上是否有线程正在等待和有多少线程正在等待。用锁的hasWaiters(Condition condition)方法查询Condition上是否有线程正在等待,再用getWaitQueueLength(Condition condition)方法获取Condition上等待的线程的个数。
现在介绍如何判断任意线程是否已持有写锁。
2.判断任意线程是否持有写锁isWriteLocked()方法
我们可以使用isWriteLocked()方法来判断任意线程是否持有写锁。
请问这个方法有什么用呢?
isWriteLocked()方法可以让我们随时查询写锁是否已经被其他线程持有了,根据查询结果我们就可以做出相应的操作。比如,写锁已经被其他线程持有了,我们现在是等还是结束线程。
既然isWriteLocked()方法是判断当前线程是否获取到写锁,那么我们的isWriteLocked()方法就只跟ReentrantReadWriteLock可重入读写锁有关了,跟ReentrantLock可重入锁无关。
下面我们就来看看isWriteLocked()方法。
isWriteLocked()方法在ReentrantReadWriteLock类中的源码:
判断任意线程是否持有写锁,当任意线程持有写锁时,方法返回true,否则返回false。
去掉注释版:
isWriteLocked()方法作用是判断任意线程是否持有写锁,当任意线程持有写锁时,方法返回true,否则返回false。
访问权限
public:isWriteLocked()方法是公开的。
boolean:isWriteLocked()方法返回boolean类型的值,当任意线程持有写锁时返回true,否则返回false。
isWriteLocked()方法只能被对象调用。
参数
无。
抛出的异常
无。
应用
下面我们就来试试isWriteLocked()方法。
首先,创建出读写锁对象:
其次,创建出读锁与写锁:
然后,让主线程去获取写锁:
最后,在获取写锁内外各调用isWriteLocked()方法并输出结果:
例子书写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。主线程在没有获取到写锁之前isWriteLocked()方法返回false,在获取到写锁之后isWriteLocked()方法返回true。
3.任意线程与当前线程
上一小节说过,isWriteLocked()方法返回的是当任意线程持有写锁时返回true,否则返回false。
任意线程与当前线程在例子中指的是?
还是把例子改写之后再说吧,有对比之后比较容易说清楚。
上一小节中只有主线程一个线程在竞争写锁,我们这时新建一个线程出来,并重写run()方法:
让新建的线程去竞争写锁:
并且在获取到写锁之后睡3秒钟:
然后,启动线程:
最后,在启动线程之后,使主线程睡1秒钟,再获取写锁:
例子改写完毕。
运行程序,执行结果:
从运行结果来看,符合预期。
任意线程指的是?
例子中,任意线程指的是无论是主线程还是新创建出来的thread线程,谁获取了写锁,isWriteLocked()方法都会返回true。
当前线程呢?
当前线程指的是执行isWriteLocked()方法的线程。
比如,在thread线程里面执行的Thread.sleep()方法,那么当前线程指的就是thread线程;
在主线程里面执行的Thread.sleep()方法,那么当前线程指的就是主线程。
当然了,我们ReentrantReadWriteLock类里面还有一个判断当前线程释放持有写锁的方法,叫isWriteLockedByCurrentThread()。
4.isWriteLocked()方法与isWriteLockedByCurrentThread()方法对比
下面,修改上一小节例子。
在主线程获取写锁的前后各调用一次isWriteLockedByCurrentThread()方法:
并且在释放锁之后再调用一次:
例子修改完毕,通过运行结果来对比isWriteLocked()方法与isWriteLockedByCurrentThread()方法的区别。
运行程序,执行结果:
静图:
从运行结果来看,符合预期。
为什么符合预期?
我们可以很明显地从运行结果中看到,当其他线程已经持有写锁的情况下,isWriteLocked()方法返回的是true,isWriteLockedByCurrentThread()方法返回的是false。
在主线程获取到写锁时,isWriteLocked()方法和isWriteLockedByCurrentThread()方法都返回的是true。
在没有线程获取写锁时(即所有线程都释放了写锁),isWriteLocked()方法和isWriteLockedByCurrentThread()方法都返回的是false。
这样一来,isWriteLocked()方法和isWriteLockedByCurrentThread()方法的区别显而易见了:
isWriteLocked()方法用于判断当任意线程持有写锁时,方法返回true,否则返回false。
isWriteLockedByCurrentThread()方法用于判断当当前线程持有写锁时,方法返回true,否则返回false。
请大家一定一定要注意!!!
最后,希望大家可以把这个例子照着写一遍,然后再自己默写一遍,方便以后碰到类似的面试题可以轻松应对。
祝大家编码愉快!
GitHub
本章程序GitHub地址:https://github.com/gorhaf/Java2019/tree/master/Thread/ReadWriteLock/ReentrantReadWriteLock
总结
- isWriteLocked()方法用于判断当任意线程持有写锁时,方法返回true,否则返回false。
- isWriteLockedByCurrentThread()方法用于判断当当前线程持有写锁时,方法返回true,否则返回false。
至此,Java中判断任意线程是否已持有写锁相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
下一章
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
閱讀更多 人人都是程序員 的文章