前言

回顾前面:

只有光头才能变强!

上一篇已经将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. Spring Security 入门(3-11)Spring Security 的使用-自定义登录验证和回调地址

    配置文件 security-ns.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  2. maven常见问题处理(3-1)修改maven 默认使用的 jdk 版本

    Eclipse工程应设定了1.8,maven编译仍然使用1.6的解决办法 解决方式有两种,一种是配置 pom.xml,一种是配置 settings.xml. 方式一:settings.xml 配置 打 ...

  3. python学习之路01

    python自己也自学过一段时间了,看过视频,也买过几本基础的书来看,目前为止对于一些简单的代码还是可以看懂,但是自己总是觉得缺少些什么,可能是缺少系统化的学习,也可能是缺少实际项目经验,对于这些缺少 ...

  4. EasyUI DataGrid - 嵌套的DataGrid

    实现效果: 一.在页面头部引用视图脚本JS文件 <script src="@Url.Content("~/Resources/EasyUI/plugins/datagrid- ...

  5. shell:bash环境

    1.什么是shell shell一般代表两个层面的意思,一个是命令解释器,比如BASH,另外一个是shell脚本. 命令解释器shell的发展史,sh-csh-ksh-tcsh-bash. 2.命令的 ...

  6. Qt QFile文件读写

    QFile 需要添加 #Include  <QFile> 集成至QIODevice 打开一个文件有3种方式QIODevice::(ReadOnly/WriteOnly/ReadWrite) ...

  7. codewars.DNA题目几种解法分析(字符串替换)

    题干: 意思就是字符串替换,"A"与"C"配对,"T"与"G"配对,DNA不为空. 解法一:我的解法,用for循环遍历字 ...

  8. C# Post提交数据

    /// <summary> /// Post提交数据 /// </summary> /// <param name="postUrl">URL& ...

  9. PHP 安装与配置(WIN10)

    需要在本地搭个PHP的测试环境,顺手将过程写了下来. 由于不是生产环境,我这里直接选择了最新的PHP版本用来测试. 本地坏境为:windows 10 Pro 1709 PHP版本:php-7.2.3- ...

  10. 多线程利器---队列(queue)

    列表是不安全的数据结构 import threading,time li=[1,2,3,4,5] def pri(): while li: a=li[-1] print(a) time.sleep(1 ...