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

简介: 哈喽,大家好,我是指北君。今天为你带来的是 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

相关文章
|
安全 数据库
就业冰点,你为什么要裸辞? by彭文华
就业冰点,你为什么要裸辞? by彭文华
《人间清醒语录》
今天,我们想分享来自大淘宝技术工程师们的《人间清醒语录》,这些金句里凝结了他们多年实践经验的智慧,希望可以给你“打怪升级”的过程带来一些帮助。
243 0
回首2022,烟火如常,布衣剩饭,啥也没干,年终总结,蹈海难酬
开篇明义,2022年,我啥也没干,或者说的更准确一些,啥也没干成,没有什么值得拿出来凡尔赛一下的事情,或者可以满足一下虚荣心的成就,300多个日夜里,就是日复一日的起床、上班、讲课、下班、吃饭、睡觉。有什么可总结的呢?
回首2022,烟火如常,布衣剩饭,啥也没干,年终总结,蹈海难酬
|
存储 安全 关系型数据库
我,卷王!
MySQL 里面表级别的锁有这几种: • 表锁; • 元数据锁(MDL); • 意向锁; • AUTO-INC 锁;
我,卷王!
|
机器学习/深度学习
学霸、学神OR开挂
我们学习知识 好比武侠世界里的人修炼武功一般 有人天赋异禀、骨骼清奇 是天生的练武奇才——学神 有人天资平庸,但通过后天的孜孜不倦 终成一代大侠——学霸 还有人一路奇遇不断,屡获高人指点 成为绝世高手——外挂玩家
学霸、学神OR开挂
端午还在“修锁”?你是真的卷王!(二)
今天为你带来的是 ReentrantLock 公平锁与非公平锁的源码分析,它是 Java 并发包下的一个 java.util.concurrent.locks 实现类,实现了 Lock 接口和 Serializable 接口。
端午还在“修锁”?你是真的卷王!(二)