前言

回顾前面:

只有光头才能变强!

上一篇已经将Lock锁的基础AQS简单地过了一遍了,因此本篇主要是讲解Lock锁主要的两个子类:

  • ReentrantLock
  • ReentrantReadWriteLock

那么接下来我们就开始吧~

一、ReentrantLock锁

首先我们来看看ReentrantLock锁的顶部注释,来看看他的相关特性呗:

来总结一下要点吧:

  • 比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内部类

首先我们可以看到有三个内部类:

这些内部类都是AQS的子类,这就印证了我们之前所说的:AQS是ReentrantLock的基础,AQS是构建锁、同步器的框架

  • 可以很清晰的看到,我们的ReentrantLock锁是支持公平锁和非公平锁的~

1.2构造方法

1.3非公平lock方法

尝试获取锁,获取失败的话就调用AQS的acquire(1)方法

acquire(1)方法我们在AQS时简单看过,其中tryAcquire()是子类来实现的

我们去看看tryAcquire()

1.4公平lock方法

公平的lock方法其实就多了一个状态条件

这个方法主要是判断当前线程是否位于CLH同步队列中的第一个。如果是则返回flase,否则返回true

1.5unlock方法

unlock方法也是在AQS中定义的:

去看看tryRelease(arg)是怎么实现的:

二、ReentrantReadWriteLock

我们知道synchronized内置锁和ReentrantLock都是互斥锁(一次只能有一个线程进入到临界区(被锁定的区域))

而ReentrantReadWriteLock是一个读写锁

  • 取数据的时候,可以多个线程同时进入到到临界区(被锁定的区域)
  • 数据的时候,无论是读线程还是写线程都是互斥

一般来说:我们大多数都是读取数据得多,修改数据得少。所以这个读写锁在这种场景下就很有用了!

读写锁有一个接口ReadWriteLock,定义的方法就两个:

我们还是来看看顶部注释说得啥吧:

其实大概也是说明了:在读的时候可以共享,在写的时候是互斥的

接下来我们还是来看看对应的实现类吧:

按照惯例也简单看看它的顶部注释:

于是我们可以总结出读写锁的一些要点了:

  • 读锁不支持条件对象,写锁支持条件对象
  • 读锁不能升级为写锁,写锁可以降级为读锁
  • 读写锁也有公平和非公平模式
  • 读锁支持多个读线程进入临界区,写锁是互斥的

2.1ReentrantReadWriteLock内部类

ReentrantReadWriteLock比ReentrantLock锁多了两个内部类(都是Lock实现)来维护读锁和写锁,但是主体还是使用Syn

  • WriteLock
  • ReadLock

2.2读锁和写锁的状态表示

在ReentrantLock锁上使用的是state来表示同步状态(也可以表示重入的次数),而在ReentrantReadWriteLock是这样代表读写状态的:

2.3写锁的获取

主要还是调用syn的acquire(1)

进去看看实现:

2.4读锁获取

写锁的获取调用的是acquireShared(int arg)方法:

内部调用的是:doAcquireShared(arg);方法(实现也是在Syn的),我们来看看:

三、最后

这里就简单总结一下本文的内容吧:

  • AQS是ReentrantReadWriteLock和ReentrantLock的基础,因为默认的实现都是在内部类Syn中,而Syn是继承AQS的~
  • ReentrantReadWriteLock和ReentrantLock都支持公平和非公平模式,公平模式下会去看FIFO队列线程是否是在队头,而非公平模式下是没有的
  • ReentrantReadWriteLock是一个读写锁,如果读的线程比写的线程要多很多的话,那可以考虑使用它。它使用state的变量高16位是读锁,低16位是写锁
  • 写锁可以降级为读锁,读锁不能升级为写锁
  • 写锁是互斥的,读锁是共享的

总的来说看多线程源码难度系数还是好高啊,我目前的水平只能过一过了....

多线程后面还有挺多高深的知识点:Future、同步容器啊、阻塞队列、各种原子类啊等等等,这里我打算就先放一放了,目前的水平有限啊~~~~~

后面可能会有一篇线程池的博文,敬请期待咯~

有兴趣的同学可继续往下面的参考资料下学习~~~

参考资料:

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。谢谢支持了!希望能多介绍给其他有需要的朋友

文章的目录导航

Lock锁子类了解一下的更多相关文章

  1. Object对象你真理解了吗?

    前言 五一回家又断更了一个放假时间了~~~ 只有光头才能变强 回顾前面: ThreadLocal就是这么简单 多线程三分钟就可以入个门了! 多线程基础必要知识点!看了学习多线程事半功倍 Java锁机制 ...

  2. 【Java】几道让你拿offer的知识点

    前言 只有光头才能变强 之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来.最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下. 文本的知识点: Inte ...

  3. java 备用待迁移

    Java基础 2018年如何快速学Java 泛型就这么简单 注解就这么简单 Druid数据库连接池就是这么简单 Object对象你真理解了吗? JDK10都发布了,nio你了解多少? COW奶牛!Co ...

  4. 在多线程编程中lock(string){...}隐藏的机关

    常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行. 这样的想法很好,至少比 lock( ...

  5. Java并发包中Lock的实现原理

    1. Lock 的简介及使用 Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制.本质上Lock仅仅是一个接口(位于源码包中的java\util\concurrent\l ...

  6. 关于boost的thread的mutex与lock的问题

    妈的,看了好久的相关的知识,感觉终于自己有点明白了,我一定要记下来啊,相关的知识呀.... 1, 也可以看一下boost的线程指南:http://wenku.baidu.com/link?url=E_ ...

  7. boost库中thread多线程详解2——mutex与lock

    1. mutex对象类 mutex类主要有两种:独占式与共享式的互斥量.▲ 独占式互斥量:mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型try_mutex: 它是mutex的同义词,为了 ...

  8. lock订单号

    常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行. 这样的想法很好,至少比 lock( ...

  9. Java类锁和对象锁实践(good)

    一.前言 之前对类锁和对象锁是否是互斥的不是太确定,因此决定编写相关的程序进行实践一下.编写前对相关定义约定约定如下: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者 ...

随机推荐

  1. OAuth2.0学习(1-7)授权方式4-客户端模式(Client Credentials Grant)

    授权方式4-客户端模式(Client Credentials Grant) 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提 ...

  2. python 面向对象进阶之内置方法

    一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...

  3. centOs6.5配置jdk及其注意事项

    1.下载jdk1.7 百度云链接: https://pan.baidu.com/s/15vXLO2eV18eVvmt-R5jGnQ 密码: 1gd6 2.解压压缩包 通过终端在/usr/local下新 ...

  4. Django实现发邮件

    1 首先去自己的邮箱申请,在设置里面找,申请开通smtp服务,我用的是163邮箱 2 在项目下settings.py中添加设置: # 配置邮箱发邮件的相关功能 #这一项是固定的 EMAIL_BACKE ...

  5. Python基础数据类型之集合以及其他和深浅copy

    一.基础数据类型汇总补充 list  在循环一个列表时,最好不要删除列表中的元素,这样会使索引发生改变,从而报错(可以从后向前循环删除,这样不会改变未删元素的索引). 错误示范: lis = [,,, ...

  6. vue2.0项目引入element-ui

    在项目中,为了方便我们工作和开发效率,常常引入一些框架来帮助我们完成高效的工作,今天我们就用vue来搭建一下框架,并且引入element-ui这个框架.安装流程也是我从失败中摸索到的,希望能帮助大家. ...

  7. JavaScript是如何面向对象的

    一.引言 在16年的10月份,在校内双选会找前端实习的时候,hr问了一个问题:JavaScript的面向对象理解吗?我张口就说"JavaScript是基于原型的!".然后就没什么好 ...

  8. JSON.stringify()和JSON.parse()分别是什么

    JSON.stringify() 从一个对象中解析出字符串 JSON.stringify({"a":"1","b":"2" ...

  9. Multipath在OpenStack中的faulty device的成因及解决(part 1)

    | 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 简介: Multip ...

  10. Windows下使用PSCP从Linux下载或上传文件

    1. 先下载putty包,然后解压 https://the.earth.li/~sgtatham/putty/latest/w64/putty.zip 2. 下载Linux文件到当前目录 PSCP.e ...