端午还在“修锁”?你是真的卷王!(一)

简介: 哈喽,大家好,我是指北君。今天为你带来的是 ReentrantLock 公平锁与非公平锁的源码分析,它是 Java 并发包下的一个 java.util.concurrent.locks 实现类,实现了 Lock 接口和 Serializable 接口。

60.jpg


初识


ReentrantLock 类有两个构造函数,一个是默认的不带参数的构造函数,创建一个默认的非公平锁的实现,一个是带参数的构造函数,根据参数 fair 创建一个公平还是非公平的锁。

61.png

这里简单的说一下公平锁和非公平锁的定义:

  1. 公平锁:线程在同步队列中通过先进先出(FIFO)的方式获取锁,每个线程最终都能获取锁。
  2. 非公平锁:线程可以通过插队的方式抢占锁,抢不到锁就进入同步队列排队。

NonfairSync 类和 FairSync 类继承了 Sync 类,它们三个都是 ReentrantLock 的内部类。

AbstractQueuedSynchronizer,简称 AQS,拥有三个核心组件:

  1. state:volatile 修饰,线程是否可以获取锁。
  2. Node:内部队列,双向链表形式,没有抢到锁的对象就进入这个队列。主要字段有:pre 前一个节点,next 下一个节点,thread 线程,waitStatus 线程的状态。
  3. exclusiveOwnerThread:当前抢到锁的线程。

如下图,简单的了解一下 AQS。

62.png

63.png


公平锁


在分析公平锁之前,先介绍一下 Sync 类,它是 ReentrantLock 的唯一的属性,在构造函数中被初始化,决定了用公平锁还是非公平锁的方式获取锁。

64.png


用以下构造方法创建一个公平锁。65.png沿着 lock.lock() 调用情况一路往下分析。

66.png


acquire() 方法主要是干了 3 件事情

  1. tryAcquire() 尝试获取锁。
  2. 获取锁失败后,调用 addWaiter() 方法将线程封装成 Node,加入同步队列。
  3. acquireQueued() 将队列中的节点按自旋的方式尝试获取锁。


67.png

tryAcquire() 尝试获取锁,如果线程本身持有锁,则将这个线程重入锁。

68.png

hasQueuedPredecessors() 这个方法比较有绅士风度,在 tryAcquire() 方法中被第一个调用,它谦让比自己排队长的线程。

69.png

相关文章
|
2月前
|
NoSQL 关系型数据库 MySQL
2024 RedisAnd Mysql基础与进阶操作系列(17)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
如何通过php和python客户端来操作Redis数据库等保姆式具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
存储 NoSQL 关系型数据库
2024 RedisAnd Mysql基础与进阶操作系列(13)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis之Nosql数据库分类、存储类型、特点;Redis 作用、与其他库的对比、使用场景以及如何部署、安装等具体详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
NoSQL 关系型数据库 Redis
2024 RedisAnd Mysql基础与进阶操作系列(18)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis 如何高级应用之密码防护、数据持久化、基于文件追加方式持久化、主从同步、消息订阅类型与之对应的命令、事务从开始到执行会经历以下三个阶段、多数据库等保姆式具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
存储 NoSQL 关系型数据库
2024 RedisAnd Mysql基础与进阶操作系列(16-2)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis数据类型之Hash类型及NCR/DECR/INCRBY/DECRBY、 GETSET、SETNX、SETRANGE/GETRANGE、SETBIT/GETBIT、MSET/MGET/MSETNX等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
机器学习/深度学习 NoSQL 关系型数据库
2024 RedisAnd Mysql基础与进阶操作系列(16-1)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis数据类型之string类型及操作:含【NCR/DECR/INCRBY/DECRBY、 GETSET、SETNX、SETRANGE/GETRANGE、SETBIT/GETBIT、MSET/MGET/MSETNX等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
存储 NoSQL 关系型数据库
2024 RedisAnd Mysql基础与进阶操作系列(15)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
2024全网最全切最为详细的Redis库配置;你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽
|
2月前
|
NoSQL 关系型数据库 MySQL
2024 RedisAnd Mysql基础与进阶操作系列(19)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis应用场景之取最新N个数据的操作、精准设定过期时间、计数器应用、Uniq操作,获取某段时间所有数据排重值、Pub/Sub构建实时消息系统等保姆式具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
NoSQL 关系型数据库 MySQL
2024 RedisAnd Mysql基础与进阶操作系列(16-3)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis数据类型之List类型语法格式说明表及LPUSH/LPUSHX/LRANGE、LPOP/LLEN、LREM/LSET/LINDEX/LTRIM、LINSERT RPUSH/RPUSHX/RPOP/RPOPLPUSH等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
存储 NoSQL 关系型数据库
2024 RedisAnd Mysql基础与进阶操作系列(16-4)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis数据类型之Set类型及相关命令如:SADD/SMEMBERS/SCARD/SISMEMBER、SPOP/SREM/SRANDMEMBER/SMOVE、SDIFF/SDIFFSTORE/SINTER/SINTERSTORE 等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
2月前
|
NoSQL 关系型数据库 MySQL
2024 RedisAnd Mysql基础与进阶操作系列(16-5)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
Redis数据类型之ZSet类型及相关命令如:SADD/SMEMBERS/SCARD/SISMEMBER、ZRANGEBYSCORE/ZREMRANGEBYRANK/ZREMRANGEBYSCORE、ZREVRANGE/ZREVRANGEBYSCORE/ZREVRANK等命令具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法