java源码-ReentrantLock源码分析-1
ReentrantLock 继承于lock是比较常用的独占锁,接下来我们来分析一下ReentrantLock源码以及接口设计:
Sync是ReentrantLock的内部静态抽象类继承AbstractQueuedSynchronizer类,ReentrantLock类部还有两个类FairSync(公平锁)跟NonfairSync(非公平锁)类实现Sync;
ReentrantLock默认内部是构建非公平锁,也可以制定使用公平锁跟非公平锁,


当调用lock()方法时,下面分析公平锁跟非公平区别:
lock()具体指向内部实例化的Sync对象

公平锁lock()方法直接调用acquire(1)直接尝试获取一次锁(第一次由于锁被抢占,加入队列时判断是否锁已经释放),如果失败后则加入队列

非公平锁,首先通过cas强行获取一次锁,失败后在调用acquire(1)尝试获取锁失败后加入队列

tryAcquire(1)方法实现也不同 非公平锁最终会调用Sync对象的nofairTryAcquire()方法,当state=0代表没有锁占用,此时会调用cas强行占用锁,
这时候如果同时新加入的线程抢占锁失败,导致后加入的锁进入队列,这时候体现无序不公平。

公平锁首先hasQueuedPredecessors()判断没有前驱节点代表是head节点然后再获取锁,

不管是公平锁还是非公平锁都支持重入锁,直接把state计数+1;
acquireQueued()方法主要左右是将实例化当前线程绑定Node节点加入队列并修改前驱节点Node的waitStatus为SIGNAL,同时并挂起当前节点;
首先new Node节点绑定线程,独占锁默认nextWaiter为空,如果存在tail节点然后通过cas添加tail节点,如果不存在会调用enq(node)方法初始化head节点

此时再次判断tail节点是否为空,如果为空然后cas添加一个空节点然后进入空转,下次循环再cas添加节点都tail节点,这里有人会疑问为什么会添加一个空Node节点而且并没有
绑定线程?

首先获取前驱节点,如果前驱节点是头节点,然后尝试获取一下锁,如果成功则设置当前node为head节点然后将前驱节点移除队列;
如果前驱节点不是头节点或者获取锁失败,此时进入shouldParkAfterFailedAcquire()方法

如果前驱节点是SIGNAL=-1则表示是可以挂起线程,等待前驱节点唤醒,如果前驱节点是刚才new Node() 的话
ws=0此时将会cas修改状态为SIGNAL,然后返回false然后进入自旋,再次进入此方法则再挂起当前线程。最后形成的链表处tail节点都是signal状态切线程状态都是挂起,
等待释放然后唤起header节点的next节点。

java源码-ReentrantLock源码分析-1的更多相关文章
- Java并发编程-ReentrantLock源码分析
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
- Java并发之ReentrantLock源码解析(二)
在了解如何加锁时候,我们再来了解如何解锁.可重入互斥锁ReentrantLock的解锁方法unlock()并不区分是公平锁还是非公平锁,Sync类并没有实现release(int arg)方法,这里会 ...
- Java并发之ReentrantLock源码解析(四)
Condition 在上一章中,我们大概了解了Condition的使用,下面我们来看看Condition再juc的实现.juc下Condition本质上是一个接口,它只定义了这个接口的使用方式,具体的 ...
- Java并发编程 ReentrantLock 源码分析
ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. 这个类主要基于AQS(Abst ...
- java源码-ReentrantLock源码分析-2
继续上篇ReentrantLock分析如何唤醒线程: 当调用lock.unlock()方法最终调用AQS类中的release方法,开始释放锁 tryRelease(1)方法在Sync对象中实现,首先会 ...
- Java并发之ReentrantLock源码解析(三)
ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...
- Java并发之ReentrantLock源码解析(一)
ReentrantLock ReentrantLock是一种可重入的互斥锁,它的行为和作用与关键字synchronized有些类似,在并发场景下可以让多个线程按照一定的顺序访问同一资源.相比synch ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- Java并发编程之ReentrantLock源码分析
ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比Re ...
随机推荐
- PAT1005 继续(3n+1)猜想
卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时 ...
- Gradle 配置国内镜像
项目级配置 在项目中找到如下文件 打开,添加上阿里云镜像 maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
- python脚本攻略之log日志
1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不同 ...
- Git 基本操作及命令
认证部分 1.配置用户信息 git config --global user.name [username] git config --global user.email [email] 2.查询用户 ...
- linux安装locust及遇到的坑
安装locust很简单,简单的我以为pip install一下就好了,结果运行locust死活不行,后来的后来,,才搞清楚还要进行以下操作. 前提: 1.已安装Python3和pip3(或者都是2,版 ...
- BZOJ 3270: 博物馆 概率与期望+高斯消元
和游走挺像的,都是将概率转成期望出现的次数,然后拿高斯消元来解. #include <bits/stdc++.h> #define N 23 #define setIO(s) freope ...
- poj 3050 Hopscotch DFS+暴力搜索+set容器
Hopscotch Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2774 Accepted: 1940 Description ...
- MySQL基础入门之常用命令使用
如何启动MySql服务 /etc/init.d/mysqld start service mysqld start Centos .x 系统 sysctl start mysqld 检测端口是否运行 ...
- Java线程之synchronized
翻译:https://www.journaldev.com/1061/thread-safety-in-java 我们知道线程安全在Java中是一个非常重要的主题,当多个线程操作共享数据时,如果没有任 ...
- android 开发随手记
1.Fragment 跳转到Activity 修改数据,修改完后从Activity 返回(返回键)Fragment ,要求刷新Fragment界面的数据 解决办法: 在Fragment中注册一个监听广 ...