Source code interpretation of other methods of ReentrantLockd

//Other methods of Reentrant:
//First look at the lockInterruptibly method, which is mainly used to acquire locks if the thread is not interrupted
 public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

     public final void acquireInterruptibly(int arg)
            throws InterruptedException {
	 //If the current thread has been interrupted, throw an exception
        if (Thread.interrupted())
            throw new InterruptedException();
	 // try to acquire the lock
        if (!tryAcquire(arg))
	    // did not acquire the lock
            doAcquireInterruptibly (arg);
    }


private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
	// enqueue
        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 ())
		    // thrown exception when interrupted
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

 /**
 Most of the process of this method and the lock() method are the same, and the most important thing is that the judgment of interrupt is added.
 When first trying to acquire the lock, determine whether the current thread has been interrupted.
 After joining the queue, when suspending the current thread, it will determine whether the current thread has been interrupted.
 Judgment twice. The rest of the process is the same as lock().
 */


 //Look at the tryLock method, if the attempt to acquire the lock returns true if it succeeds, it returns false if it fails.
 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;
        }

/** This method attempts to acquire the lock, returns true if the acquisition is successful, and returns false if it fails*/


//Look at the overloaded method of 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 the thread is interrupted throw an exception
        if (Thread.interrupted())
            throw new InterruptedException();
	  // try to acquire the lock
        return tryAcquire(arg) ||

            doAcquireNanos(arg, nanosTimeout);
    }

    private boolean doAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
        long lastTime = System.nanoTime ();
	// enqueue
        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;
                }
		// timed out
                if (nanosTimeout <= 0)
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
		    //nanosTimeout> 1 second to suspend. Because the time is too short, the suspend time may have exceeded the spin time.
                    nanosTimeout> spinForTimeoutThreshold)
		    // Suspend the current thread
                    LockSupport.parkNanos(this, nanosTimeout);
		    //calculating time
                long now = System.nanoTime();
                nanosTimeout -= now - lastTime;
                lastTime = now;
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /** This method refers to acquiring the lock within the specified time */


    //getHoldCount() returns the number of times the current thread holds the lock
    public int getHoldCount() {
        return sync.getHoldCount();
    }

     final int getHoldCount() {
            //The current thread is an exclusive thread
            return isHeldExclusively() ? getState() : 0;
        }
    //Return whether the thread is called in exclusive mode
     protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }


   //isHeldByCurrentThread() Query whether the current thread owns the lock
   public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }
    protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

   //isLock() Query whether the lock is already owned
   public boolean isLocked() {
        return sync.isLocked();
    }
     final boolean isLocked() {
            return getState() != 0;
        }

   //isFair() Determine whether the lock is a fair lock
   public final boolean isFair() {
        return sync instanceof FairSync;
    }

   //getOwner() returns the thread that owns the current lock
    protected Thread getOwner() {
        return sync.getOwner();
    }
   /**
   This method is a bit strange. Why should you judge getState instead of getExclusiveOwnerThread() directly?
   Because private volatile int state; state is volatile and safe.
   And private transient Thread exclusiveOwnerThread. There is no guarantee of memory visibility without the volatile keyword.
   */
    final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

   / / Determine whether there is a thread queue waiting for this lock
   public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
    /** When the thread joins the queue, if the queue is empty, a node will be initialized as the head node and tail node.
    So if the head node and the tail node are equal, there is no intermediate node and the queue is empty.
    */
    public final boolean hasQueuedThreads() {
        return head != tail;
    }


   //Query whether the given thread is waiting for this lock
   public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    public final boolean isQueued(Thread thread) {
        if (thread == null)
            throw new NullPointerException();
	 // Find this thread from the start of the team
        for (Node p = tail; p != null; p = p.prev)
            if (p.thread == thread)
                return true;
        return false;
    }


  //getQueueLength() returns the estimated number of threads waiting for the lock
   public final int getQueueLength() {
        return sync.getQueueLength();
    }

   public final int getQueueLength() {
        int n = 0;
	// Search from the end of the queue like the front
        for (Node p = tail; p != null; p = p.prev) {
            if (p.thread != null)
                ++n;
        }
        return n;
    }

    //getQueuedThreads() gets all the threads waiting to be encapsulated into ArrayList
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }
    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
	// Traverse all nodes from the end of the queue
        for (Node p = tail; p != null; p = p.prev) {
            Thread t = p.thread;
            if (t != null)
                list.add(t);
        }
        return list;
    }

   //Query whether there are threads waiting to wait on this condition pair.
    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) {
     //Determine whether the condition is owned by the current 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();
	   //Start from the beginning to find if there is a node with waitStatus equal to CONDITION. If there is, it means that there are threads waiting on the condition
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }


     //Get the estimated number on the current condition waiting thread
     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;
        }  

     //Get the thread waiting on the condition and encapsulate it into 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;
        }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326568530&siteId=291194637