Lock锁子类了解一下
前言
回顾前面:
- 多线程三分钟就可以入个门了!
- Thread源码剖析
- 多线程基础必要知识点!看了学习多线程事半功倍
- Java锁机制了解一下
- AQS简简单单过一遍
只有光头才能变强!上一篇已经将Lock锁的基础AQS简单地过了一遍了,因此本篇主要是讲解Lock锁主要的两个子类:
- ReentrantLock
- ReentrantReadWriteLock
一、ReentrantLock锁 首先我们来看看ReentrantLock锁的顶部注释,来看看他的相关特性呗:
文章图片
image 来总结一下要点吧:
- 比synchronized更有伸缩性(灵活)
- 支持公平锁(是相对公平的)
- 使用时最标准用法是在try之前调用lock方法,在finally代码块释放锁
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...public void m() {
lock.lock();
// block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
1.1内部类 首先我们可以看到有三个内部类:
文章图片
image 这些内部类都是AQS的子类,这就印证了我们之前所说的:AQS是ReentrantLock的基础,AQS是构建锁、同步器的框架
- 可以很清晰的看到,我们的ReentrantLock锁是支持公平锁和非公平锁的~
文章图片
image 1.2构造方法
文章图片
image 1.3非公平lock方法 尝试获取锁,获取失败的话就调用AQS的
acquire(1)
方法文章图片
image
acquire(1)
方法我们在AQS时简单看过,其中tryAcquire()
是子类来实现的文章图片
image 我们去看看
tryAcquire()
:文章图片
R8boDld.png 1.4公平lock方法 公平的lock方法其实就多了一个状态条件:
文章图片
image 这个方法主要是判断当前线程是否位于CLH同步队列中的第一个。如果是则返回flase,否则返回true。
文章图片
hEQLRhM.png 1.5unlock方法
文章图片
image unlock方法也是在AQS中定义的:
文章图片
image 去看看
tryRelease(arg)
是怎么实现的:文章图片
image 二、ReentrantReadWriteLock 我们知道synchronized内置锁和ReentrantLock都是互斥锁(一次只能有一个线程进入到临界区(被锁定的区域))
而ReentrantReadWriteLock是一个读写锁:
- 在读取数据的时候,可以多个线程同时进入到到临界区(被锁定的区域)
- 在写数据的时候,无论是读线程还是写线程都是互斥的
读写锁有一个接口ReadWriteLock,定义的方法就两个:
文章图片
5vTThVt.png 我们还是来看看顶部注释说得啥吧:
文章图片
jOQwGT4.png 其实大概也是说明了:在读的时候可以共享,在写的时候是互斥的
接下来我们还是来看看对应的实现类吧:
文章图片
dnXOqm6.png 按照惯例也简单看看它的顶部注释:
文章图片
image 于是我们可以总结出读写锁的一些要点了:
- 读锁不支持条件对象,写锁支持条件对象
- 读锁不能升级为写锁,写锁可以降级为读锁
- 读写锁也有公平和非公平模式
- 读锁支持多个读线程进入临界区,写锁是互斥的
- WriteLock
- ReadLock
文章图片
image 2.2读锁和写锁的状态表示 在ReentrantLock锁上使用的是state来表示同步状态(也可以表示重入的次数),而在ReentrantReadWriteLock是这样代表读写状态的:
文章图片
O0Omir0.png 2.3写锁的获取 主要还是调用syn的
acquire(1)
:文章图片
axE3ub1.png 进去看看实现:
文章图片
image 2.4读锁获取 写锁的获取调用的是
acquireShared(int arg)
方法:文章图片
image 内部调用的是:
doAcquireShared(arg);
方法(实现也是在Syn的),我们来看看:文章图片
image 三、最后 这里就简单总结一下本文的内容吧:
- AQS是ReentrantReadWriteLock和ReentrantLock的基础,因为默认的实现都是在内部类Syn中,而Syn是继承AQS的~
- ReentrantReadWriteLock和ReentrantLock都支持公平和非公平模式,公平模式下会去看FIFO队列线程是否是在队头,而非公平模式下是没有的
- ReentrantReadWriteLock是一个读写锁,如果读的线程比写的线程要多很多的话,那可以考虑使用它。它使用state的变量高16位是读锁,低16位是写锁
- 写锁可以降级为读锁,读锁不能升级为写锁
- 写锁是互斥的,读锁是共享的。
多线程后面还有挺多高深的知识点:Future、同步容器啊、阻塞队列、各种原子类啊等等等,这里我打算就先放一放了,目前的水平有限啊~~~~~
后面可能会有一篇线程池的博文,敬请期待咯~
有兴趣的同学可继续往下面的参考资料下学习~~~
参考资料:
- http://cmsblogs.com/?page_id=111
如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。谢谢支持了!希望能多介绍给其他有需要的朋友【Lock锁子类了解一下】文章的目录导航:
- https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang
推荐阅读
- C语言中的时间函数clock()和time()你都了解吗
- iOS中的Block
- 边走边看——锁
- 代码不规范容易造成的bug
- 《人性的枷锁》
- 别让习惯成为可怕的枷锁
- stm32|基于STM32和freeRTOS智能门锁设计方案
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- 学习日记block众多用法中的一种用法
- Java并发编程|Java并发编程 - 深入剖析ReentrantLock之非公平锁加锁流程(第1篇)