当前位置: 首页 > news >正文

网站建设敬请期待图片素材济南12345官网

网站建设敬请期待图片素材,济南12345官网,广州注册公司地址,网站的内容与功能设计ReentrantLock源码解析 概括AQS实现构造方法lock方法公平锁执行lock方法公平锁lock流程图 非公平锁执行lock方法线程获取公平锁和非公平锁的区别 释放锁 概括 ReentrantLock,是Lock接口的实现类,我们查看其内的一些方法 我们可以发现其内大部分方法都是…

ReentrantLock源码解析

  • 概括
    • AQS实现
    • 构造方法
    • lock方法
      • 公平锁执行lock方法
        • 公平锁lock流程图
      • 非公平锁执行lock方法
        • 线程获取公平锁和非公平锁的区别
    • 释放锁


概括

ReentrantLock,是Lock接口的实现类,我们查看其内的一些方法

在这里插入图片描述
在这里插入图片描述
我们可以发现其内大部分方法都是通过sync对象来实现的,查看sync:
在这里插入图片描述
如上图,sync是一个抽象类,继承了AQS,而AQS的主要实现则是通过一个共享变量以及先进先出的队列实现,如下:

AQS实现

在这里插入图片描述
由volatile修饰的state,表示共享资源的状态,当其为0时表示资源空闲,>0时表示资源被锁定
在这里插入图片描述
而若有线程想要获取锁,就调用以上方法尝试使用CAS修改state变量,修改成功则表示成功获取锁,如果获取锁失败,线程就会被包装成结点加入先进先出的队列中,在AQS中该队列是通过双向链表实现的,如以下方法:
在这里插入图片描述

构造方法

我们已经知道大概知道了AQS的基本实现原理,而sync又继承了AQS。
查看其构造方法:

 public ReentrantLock() {sync = new NonfairSync();}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}

其包括两个构造方法,第一个构造方法不传入参数值,默认创建非公平锁,而第二个构造方法会根据传入的参数决定创建非公平锁还是公平锁,我们来看看什么是公平锁和非公平锁。
在这里插入图片描述
在这里插入图片描述
可以很清楚的看到非公平锁和公平锁都继承了Sync,并且它们存在两个相同的方法不同的具体实现。

lock方法

当调用lock方法时,会调用sync变量的lock方法,而Lock只是一个抽象类,调用时会根据不同的子类执行不同的方法
在这里插入图片描述

公平锁执行lock方法

公平锁会执行如下的方法:

    public final void acquire(int arg) {if (// 尝试获取锁。。。(1)!tryAcquire(arg) &&//如果获取锁失败将执行该方法.。。。(2)acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}

查看(1):

        protected final boolean tryAcquire(int acquires) {// 获取当前线程final Thread current = Thread.currentThread();//获取状态码stateint c = getState();//如果状态码为0表示锁是空闲的if (c == 0) {// 判断等待队列是否为nullif (!hasQueuedPredecessors() &&//如果为null线程通过CAS修改state变量compareAndSetState(0, acquires)) {//如果修改成功设置持有锁的线程返回truesetExclusiveOwnerThread(current);return true;}}// 如果当前的线程就是持有锁的线程,就表示该线程重入这个锁else if (current == getExclusiveOwnerThread()) {//修改state变量int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded")//通过CAS将state修改为重入的次数setState(nextc);return true;}return false;}}

我们进入以上代码的一些方法中查看:
该方法主要是判断队列中有没有其他要竞争锁的线程,如果存在当前线程就需要入队按照竞争锁的顺序来获取锁。

 public final boolean hasQueuedPredecessors() {Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return//如果等待队列的头节点就是尾结点,因为头节点是当前持有锁的线程,那么此时没有其他竞争锁的线程,当前线程有资格竞争锁h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}

设置当前持有锁的线程:

    protected final void setExclusiveOwnerThread(Thread thread) {exclusiveOwnerThread = thread;}

如果方法1返回true,则表明线程成功获取到了锁,如果返回false,则表示竞争锁失败,就会执行方法2,方法2中的参数调用了一个方法该方法会将当前线程包装成一个结点放到等待队列的尾部

    private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode);// Try the fast path of enq; backup to full enq on failureNode pred = tail;if (pred != null) {node.prev = pred;if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}enq(node);return node;}

然后执行以下方法,该方法会根据线程访问的顺序也即等待队列的顺序竞争锁

    final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;//线程进入自旋状态for (;;) {//获取当前入队结点的前驱结点final Node p = node.predecessor();//当前驱结点为头节点时(即前驱结点当前持有了锁),当前线程才有获取锁的资格,当前线程通过CAS获取锁if (p == head && tryAcquire(arg)) {//当前线程获取锁成功后,将当前结点设置为头节点,返回falsesetHead(node);p.next = null; // help GCfailed = false;return interrupted;}//判断前驱结点的状态,如果状态为撤销,直接跳过if (shouldParkAfterFailedAcquire(p, node) &&//判断线程是否被中断parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
//通过方法二的返回值,判断当前线程的中断位,可以响应中断static void selfInterrupt() {Thread.currentThread().interrupt();}
公平锁lock流程图

在这里插入图片描述

非公平锁执行lock方法

     final void lock() {//直接CAS修改state状态,尝试获取锁if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());else//竞争锁失败acquire(1);}

竞争锁失败后的逻辑与公平锁的逻辑差不多,只有第一个方法是不同的

    public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}

与公平锁不同的是,其发现state为0时直接CAS修改state获取锁

        final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}

当线程获取不到锁时,会与线程竞争公平锁的逻辑相同,会包装为结点放入等待队列,锁定前驱结点,当前驱结点获取锁时才会尝试再次获取锁,而不是一直在等待队列中尝试获取锁,这样太浪费性能了。

线程获取公平锁和非公平锁的区别

线程调用lock方法获取公平锁时,当知道锁未被持有时,首先就会通过CAS修改state变量尝试获取锁,而非空锁则会判断等待队列中是否存在等待锁的线程,如果不存在会尝试获取锁。后面的逻辑两种则相同,加入等待队列,锁定前驱结点,当前驱节点持有锁时,会尝试获取锁。

至于超时获取锁的方法,大家可以看看源码,只比lock方法增加了一个超时的逻辑。

释放锁

释放锁的逻辑相当简单,用state变量减去当前线程重入锁的此时,使用CAS设置state变量即可

    public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;}protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {free = true;setExclusiveOwnerThread(null);}setState(c);return free;}
http://www.dtcms.com/a/513775.html

相关文章:

  • 烟台网站排名优化公司哪家好电商网站的开发形式
  • 电子商务网站建设课程设计58同城网招聘找工作建筑工程
  • 怎么在自己的网站上传视频谁会写网站代码
  • php门户网站源码个人小程序免费制作平台
  • 网站推广需求silverlight 做的网站
  • 奇墙网站建设网站的二维码怎么做的
  • 做企业网站用什么cms山东网站备案 论坛
  • 基于单片机的自动换挡式高精度数字电压表设计
  • 手机端网站尺寸百度登陆页面
  • 亚马逊商城官方网站上传附件空间网站
  • 网站开发考核wordpress主题网址导航
  • 网站服务器如何做端口映射网站怎么做定位功能
  • 网站seo工作内容做网站运用的技术
  • 注册越南网站vnwordpress 素材
  • 宁波网站建设托管重庆专业网站建设公司哪家好
  • qq是腾讯的还是阿里的巩义网站优化公司
  • 网站关键词怎么设置可以直接进网站正能量小米
  • 网站评论列表模板自建网站定位
  • 简单 网站设计美工素材网站
  • 株洲营销型网站建设网站在那里
  • 更新网站的步骤wordpress评论微信通知
  • 湖北住房与城乡建设厅网站局机关门户网站建设自查报告范文
  • 东莞做网站微信巴巴淘宝网页制作素材
  • 手机网站模板制作企业网站建设合同方案
  • 【LeetCode】83. 删除排序链表中的重复元素
  • 网站建设流程咨询设计网站要包含信息类型
  • wordpress主题换字体如何结合搜索检索与seo推广
  • 中山网站建设文化机构百度推广广告收费标准
  • 网站 设计 趋势网站规划建设书
  • 孙红雷做的二手车网站公司企业网络推广