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的更多相关文章

  1. Java并发编程-ReentrantLock源码分析

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  2. Java并发之ReentrantLock源码解析(二)

    在了解如何加锁时候,我们再来了解如何解锁.可重入互斥锁ReentrantLock的解锁方法unlock()并不区分是公平锁还是非公平锁,Sync类并没有实现release(int arg)方法,这里会 ...

  3. Java并发之ReentrantLock源码解析(四)

    Condition 在上一章中,我们大概了解了Condition的使用,下面我们来看看Condition再juc的实现.juc下Condition本质上是一个接口,它只定义了这个接口的使用方式,具体的 ...

  4. Java并发编程 ReentrantLock 源码分析

    ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. 这个类主要基于AQS(Abst ...

  5. java源码-ReentrantLock源码分析-2

    继续上篇ReentrantLock分析如何唤醒线程: 当调用lock.unlock()方法最终调用AQS类中的release方法,开始释放锁 tryRelease(1)方法在Sync对象中实现,首先会 ...

  6. Java并发之ReentrantLock源码解析(三)

    ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...

  7. Java并发之ReentrantLock源码解析(一)

    ReentrantLock ReentrantLock是一种可重入的互斥锁,它的行为和作用与关键字synchronized有些类似,在并发场景下可以让多个线程按照一定的顺序访问同一资源.相比synch ...

  8. Java并发系列[5]----ReentrantLock源码分析

    在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...

  9. Java并发编程之ReentrantLock源码分析

    ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比Re ...

随机推荐

  1. shell脚本基础和grep文本处理工具企业应用3

    文本处理工具:    linux上文本处理三剑客        grep,egrep,fgrep:文本过滤工具(模式:pattern)工具            grep:默认支持的是基本正则表达式: ...

  2. C++第二次作业--函数

    1.为什么要用函数 创建 C++ 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务.通过函数我们可以实现代码复用,即可以重复使用和在各种适用情况下使用,函数的存在增强了程序的可读性.并且函 ...

  3. Google Chrome Keyboard Shortcuts

    Navigation To do this Press this Open a new window Ctrl + N Open a new tab Ctrl + T Open a new windo ...

  4. php 垃圾处理机制

    在php5.3版本之前, php变量的回收机制只是简单的通过计数来处理(当refcount=0时,会回收内存),但这样会出现一个问题 $a=array("str"); $a[]=& ...

  5. tensorflow2.0编程规范

    背景 tensorflow2.0 相比于1.0 有很大变化,1.0版本的placeholder,Session都没有了,2.0版本强推使用keras.keras是一个比较高层的api,确实挺好用的,一 ...

  6. 集合(七) Set—HashSet,TreeSet和LinkedHashSet

    四.Set Set和List一样,也是继承Collection的接口,但Set是不包含重复元素的集合.由于先啃下Map,Set的难度将会大幅减小.因为Set基本上都是以Map为基础实现的,例如两个主要 ...

  7. mysqldump恢复

    mysqldump的恢复操作比较简单,因为备份的文件就是导出的SQL语句,一般只需要执行这个文件就可以了,可以通过以下的方法. 方法一 [root@zstedu andyxi3306]# mysql ...

  8. 01- ES6、jquery源码、node、webpack

    1.课程介绍 小马哥blog:https://www.cnblogs.com/majj/ 前端学习路径:https://www.processon.com/view/link/5d3a5947e4b0 ...

  9. 【Springboot】Springboot整合Ehcache

    刚刚项目上线了,记录下使用的技术...... EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache的特点 ( ...

  10. C# dll文件添加引用失败

    未能添加对“***/***.dll”的引用.请确保此文件可访问并且是一个有效的程序集或 COM 组件. 原因:dll文件使用其他语言生成,C#无法识别 解决方法: 添加using System.Run ...