// A semaphore that allows the thread to continue execution only if the pool still has permission. // first look at the constructor //Default is unfair mode public Semaphore(int permits) { sync = new NonfairSync(permits); } NonfairSync(int permits) { super(permits); } //set state Sync(int permits) { setState(permits); } public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); } // get a license public void acquire() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) //The method in AQS is blocked without acquiring the lock doAcquireSharedInterruptibly (arg); } final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState(); int remaining = available - acquires; //If remaining<0, there is no permission. Or have permission to directly CAS try to set the value of state if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } } private void doAcquireSharedInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter (Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt ()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } // Get the specified number of licenses public void acquire(int permits) throws InterruptedException { if (permits < 0) throw new IllegalArgumentException(); sync.acquireSharedInterruptibly(permits); } // release permission public void release() { sync.releaseShared(1); } public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; } protected final boolean tryReleaseShared(int releases) { for (;;) { int current = getState(); int next = current + releases; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); //CAS sets the current number of licenses if (compareAndSetState(current, next)) return true; } } // release the specified number of licenses public void release(int permits) { if (permits < 0) throw new IllegalArgumentException(); sync.releaseShared(permits); } // get permission public void acquireUninterruptibly() { sync.acquireShared(1); } //Do not block the direct access to the license, if the acquisition fails, return false directly public boolean tryAcquire() { return sync.nonfairTryAcquireShared(1) >= 0; } // try to acquire the lock within a certain period of time and return false public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } //Return the number of available licenses for the secondary semaphore public int availablePermits() { return sync.getPermits(); } // Get all available licenses and clear the licenses public int drainPermits() { return sync.drainPermits(); } final int drainPermits() { for (;;) { int current = getState(); if (current == 0 || compareAndSetState(current, 0)) return current; } } // Reduce the current amount of available licenses protected void reducePermits(int reduction) { if (reduction < 0) throw new IllegalArgumentException(); sync.reducePermits(reduction); } final void reducePermits(int reductions) { for (;;) { int current = getState(); int next = current - reductions; if (next > current) // underflow throw new Error("Permit count underflow"); if (compareAndSetState(current, next)) return; } } // Is it fair mode public boolean isFair() { return sync instanceof FairSync; } //Check if there are threads waiting to get public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public final boolean hasQueuedThreads() { return head != tail; } //Get the number of threads waiting for permission 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; } // Encapsulate possibly waiting threads into a collection 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; }
Read Semaphore source code
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=326403778&siteId=291194637
Recommended
Ranking