`

ReentrantLockd的其他方法源码解读

阅读更多
//Reentrant的其他方法:
//先看lockInterruptibly方法,该方法主要用于如果该线程未被中断则获取锁
 public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

     public final void acquireInterruptibly(int arg)
            throws InterruptedException {
	 //如果当前线程已经被中断抛出异常
        if (Thread.interrupted())
            throw new InterruptedException();
	 //尝试获取锁
        if (!tryAcquire(arg))
	    //没有获取到锁
            doAcquireInterruptibly(arg);
    }


private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
	//入队
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
		    //被中断抛出异常
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

 /**
 该方法和lock()方法大部分过程都相同最主要是新增了中断的判断。
 刚开始尝试获得锁的时候判断当前线程是否已经被中断。
 入队后,挂起当前线程的时候又会判断当前线程是否已经被中断。
 两次判断。其余流程与lock()一致。
 */


 //看tryLock方法,尝试获取锁成功返回true,失败返回false。
 public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
  
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) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

/**该方法即尝试获取锁,获取成功返回true,失败返回false*/


//看trylock的重载方法
 public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

     public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
	  //如果线程被中断抛出异常
        if (Thread.interrupted())
            throw new InterruptedException();
	  //尝试获取锁
        return tryAcquire(arg) ||

            doAcquireNanos(arg, nanosTimeout);
    }

    private boolean doAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
        long lastTime = System.nanoTime();
	//入队
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
		//超时了
                if (nanosTimeout <= 0)
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
		    //nanosTimeout>1秒才挂起.因为时间太短的话可能挂起的时间已经超过自旋的时间。
                    nanosTimeout > spinForTimeoutThreshold)
		    //挂起当前线程
                    LockSupport.parkNanos(this, nanosTimeout);
		    //计算时间
                long now = System.nanoTime();
                nanosTimeout -= now - lastTime;
                lastTime = now;
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /** 该方法时指在指定时间内获得锁*/


    //getHoldCount()返回当前线程保持该锁的次数
    public int getHoldCount() {
        return sync.getHoldCount();
    }

     final int getHoldCount() {
            //当前线程是独占线程
            return isHeldExclusively() ? getState() : 0;
        }
    //返回是否是独占方式调用的线程
     protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }


   //isHeldByCurrentThread() 查询当前线程是否拥有此锁
   public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }
    protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

   //isLock()查询锁是否已经被拥有
   public boolean isLocked() {
        return sync.isLocked();
    }
     final boolean isLocked() {
            return getState() != 0;
        }

   //isFair() 判断该锁是否为公平锁
   public final boolean isFair() {
        return sync instanceof FairSync;
    }

   //getOwner()返回拥有当前锁的线程
    protected Thread getOwner() {
        return sync.getOwner();
    }
   /**
   这个方法有些奇怪为什么要判断getState不直接getExclusiveOwnerThread()?
   因为 private volatile int state; state是volatile的,是安全的。
   而 private transient Thread exclusiveOwnerThread。没有volatile关键字没有保证内存可见性。
   */
    final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

   //判断是否有线程队列在等待此锁
   public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
    /**在线程入队的时候,如果队列为空,会初始化一个节点作为头节点和尾节点。
    所以如果头结点和尾节点相等表示没有中间节点即队列为空。
    */
    public final boolean hasQueuedThreads() {
        return head != tail;
    }


   //查询给定线程是否在等待此锁
   public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    public final boolean isQueued(Thread thread) {
        if (thread == null)
            throw new NullPointerException();
	 //从队伍开始查找此线程
        for (Node p = tail; p != null; p = p.prev)
            if (p.thread == thread)
                return true;
        return false;
    }


  //getQueueLength()返回正在等待该锁的线程估计数
   public final int getQueueLength() {
        return sync.getQueueLength();
    }

   public final int getQueueLength() {
        int n = 0;
	//从队尾开始像前搜索
        for (Node p = tail; p != null; p = p.prev) {
            if (p.thread != null)
                ++n;
        }
        return n;
    }

    //getQueuedThreads()获取正在等待的所有线程封装到ArrayList中
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }
    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
	//从队尾开始遍历所有节点
        for (Node p = tail; p != null; p = p.prev) {
            Thread t = p.thread;
            if (t != null)
                list.add(t);
        }
        return list;
    }

   //查询是否有线程等待在该条件对上等待。
    public boolean hasWaiters(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
    }
   

    public final boolean hasWaiters(ConditionObject condition) {
     //判断该condition是否为当前sync所拥有
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.hasWaiters();
    }

    final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

    protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
	   //从头开始查找有没有waitStatus等于CONDITION的节点。有就说明有线程在该条件上等待
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }


     //获取当前condition等待线程上的预估数
     public int getWaitQueueLength(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    ++n;
            }
            return n;
        }  

     //获取该condition上等待的线程封装到Collection中
    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

     protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION) {
                    Thread t = w.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
分享到:
评论

相关推荐

    HashMap之resize()方法源码解读.docx

    HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...

    TMS320F28x源码解读 程序

    《TMS320F28x源码解读——深入理解数字信号处理器的精髓》 在数字信号处理领域,TMS320F28x系列芯片因其高性能、低功耗的特点,被广泛应用于各种复杂系统中,如工业自动化、电力控制、通信设备等。这些系统的核心...

    HashMap之put方法源码解读.docx

    HashMap 之 put 方法源码解读 HashMap 是 Java 中一种常用的数据结构,用于存储键值对。其中,put 方法是 HashMap 中最重要的方法之一,负责将键值对存储到HashMap 中。在本文中,我们将对 HashMap 的 put 方法的...

    Postgresql源码解读.docx

    4500页的源码解读 光是SELECT语句相关实现,就阐述了300多页 看完了你就是postgreSQL达人了 章节明细,需要精读那个功能点就仔细看

    源码解读:参照管理系统的功能实现.pptx

    源码解读是软件开发中的一项重要技能,它涉及到对程序源代码的深入理解和分析,以揭示系统的功能实现和设计思路。在《源码解读的基本原理》中,我们了解到源码解读能够帮助我们理解系统的运作机制,提升编程能力,并...

    菜鸟 Spring 源码解读 推荐流程

    Spring框架的设计理念和实现方式对许多其他Java框架产生了深远影响,因此深入理解Spring源码对于提升整体编程技能至关重要。 Spring框架主要由以下几个模块组成: 1. **核心容器**:这是Spring的基石,包括...

    floodlight源码解读.

    floodlight源码解读

    netty5.0架构剖析和源码解读

    Netty5.0架构剖析和源码解读,旨在为读者提供深入理解Netty内部工作机制的途径,通过源码层面的分析帮助开发者更好地掌握Netty的应用和优化。 1. JAVA的IO演进 在Netty 5.0之前,Java IO主要经历了BIO到NIO的演进...

    jQuery源码解读

    jQuery 源码解读 jQuery 是一款非常流行的 JavaScript 库,以其简洁的语法和强大的功能深受开发者喜爱。本文将深入探讨 jQuery 的源码结构和执行流程,帮助你更好地理解和运用这个库。 首先,jQuery 的核心架构是...

    Netty5.0架构剖析和源码解读.PDF

    在源码解读方面,我们可以关注以下几个关键部分: 1. **BossGroup 和 WorkerGroup 的实现**:通常基于NIO的Selector实现,BossGroup负责监听新连接,而WorkerGroup处理已连接的SocketChannel。 2. **Channel 实现*...

    PX4源码解读

    在《PX4源码解读》中,我们可以深入探讨这个系统的核心组成部分和工作原理。首先,PX4的架构由几个关键模块组成: 1. **硬件抽象层**:这层代码确保了PX4可以适应各种硬件平台,包括不同类型的传感器、处理器和通信...

    Spark-2.3.1源码解读

    Spark-2.3.1源码解读。 Spark Core源码阅读 Spark Context 阅读要点 Spark的缓存,变量,shuffle数据等清理及机制 Spark-submit关于参数及部署模式的部分解析 GroupByKey VS ReduceByKey OrderedRDDFunctions...

    高清Netty5.0架构剖析和源码解读

    Netty5.0 架构剖析和源码解读 作者:李林锋 版权所有 email neu_lilinfeng@ © Netty5.0 架构剖析和源码解读1 1. 概述2 1.1. JAVA 的IO演进2 1.1.1. 传统BIO通信的弊端2 1.1.2. Linux 的网络IO模型简介4 1.1.3. IO...

    spark 源码解读迷你书

    《Spark源码解读迷你书》是一本专注于深入理解Apache Spark核心源码的书籍,适合对大数据处理技术有深厚兴趣并且想要探索Spark内部机制的读者。在阅读这本书之前,建议先搭建好Spark开发环境,比如使用Intelij IDEA...

    VxWorks源码解读.rar

    VxWorks以其高效、确定性和微秒级的响应时间著称,它的源码解读对于我们理解其工作原理、优化系统性能以及进行定制化开发具有重要意义。 首先,我们要了解VxWorks的核心组成部分,包括内核(Kernel)、文件系统...

    JEECMS2源码的解读

    JEECMS2源码的解读,介绍JEECMS2源码的结构,开发流程等

    Vue进阶面试题,源码解读,含Vue3源码解读

    本文将针对"Vue进阶面试题,源码解读,含Vue3源码解读"这一主题,详细探讨相关知识点。 首先,对于Vue进阶面试题,通常会涉及到以下几个方面: 1. **响应式原理**:Vue基于ES6的Proxy和Reflect实现数据的响应式,...

    STM32开发板三轴联动插补源码解读,直线圆弧加减速功能解析,基于STM32F1与STM32F4源码研究,附带大量中文注释,助力学习与实践应用,基于STM32开发板的三轴联动插补直线圆弧源码解读及基于

    STM32开发板三轴联动插补源码解读,直线圆弧加减速功能解析,基于STM32F1与STM32F4源码研究,附带大量中文注释,助力学习与实践应用,基于STM32开发板的三轴联动插补直线圆弧源码解读及基于STM32F系列加速减速功能...

    第三节-springboot源码解析-王炸篇.pdf

    @RequestMapping注解用于映射Web请求到相应的处理方法上。 总而言之,通过对Spring Boot源码的解析,可以了解到Spring Boot是如何简化Spring应用的配置和部署的,其中涉及到的自动装配、条件装配和自定义启动器等...

Global site tag (gtag.js) - Google Analytics