Java multithreading: Semaphore

Source: Internet
Author: User

Semaphore provides a class for controlling a resource that can be accessed by several threads at the same time in the concurrent sending package.

Instance code:

// Allow two threads to simultaneously access final Semaphore semaphore = new Semaphore (2); ExecutorService executorService = Executors. newCachedThreadPool (); for (int I = 0; I <10; I ++) {final int index = I; executorService.exe cute (new Runnable () {public void run () {try {semaphore. acquire (); // here may be the business code System. out. println ("Thread:" + Thread. currentThread (). getName () + "License:" + index); TimeUnit. SECONDS. sleep (1); semaphore. release (); System. out. println ("allowed tasks:" + semaphore. availablePermits ();} catch (InterruptedException e) {e. printStackTrace () ;}}) ;}executorservice. shutdown ();


Constructor 1:

    public Semaphore(int permits) {        sync = new NonfairSync(permits);    }

The initial permits license, that is, the maximum number of access threads.


Constructor 2:

    public Semaphore(int permits, boolean fair) {        sync = (fair)? new FairSync(permits) : new NonfairSync(permits);    }
The initial permits license, that is, the maximum number of access threads.

When the value of fair is set to false, the thread's permission obtaining sequence is unordered. That is to say, the new thread may obtain the permission before the waiting old thread. When the value is set to true, semaphores ensure the order in which they are called (that is, FIFO and FIFO)


Main Methods:

Void acquire () is used to obtain a license from the semaphore. If no license is available, the wait will be blocked,

Void acquire (int permits) to obtain a specified number of licenses. It will be blocked until there is no available license.

Boolean tryAcquire () tries to obtain a license from the semaphore. If no license is available, false is returned directly without blocking.

Boolean tryAcquire (int permits) attempts to obtain a specified number of licenses. If no license is available, false is returned directly,

Boolean tryAcquire (int permits, long timeout, TimeUnit unit) tries to obtain permission from the semaphore within the specified time. If the permission is obtained successfully within the specified time, true is returned; otherwise, false is returned.

Void release () releases a license. Do not forget to use it in finally. Note: multiple calls to this method will increase the number of licenses for semaphores to achieve dynamic scaling, for example: when the initial permits is 1, two release calls are called, and the maximum permission is changed to 2.

Int availablePermits () to obtain the license available for the current semaphore


JDK unfair Semaphore implementation:

1. When a Semaphore object is created using the construction of a parameter, a NonfairSync object instance is created and the state value is set to the passed value (permits ),

    public Semaphore(int permits) {        sync = new NonfairSync(permits);    }
NonfairSync indirectly inherits the AbstractQueuedSynchronizer implementation
final static class NonfairSync extends Sync {        private static final long serialVersionUID = -2694183684443567898L;        NonfairSync(int permits) {            super(permits);        }        protected int tryAcquireShared(int acquires) {            return nonfairTryAcquireShared(acquires);        }    }
    abstract static class Sync extends AbstractQueuedSynchronizer {        private static final long serialVersionUID = 1192457210091910933L;        Sync(int permits) {            setState(permits);        }
SetState method of AbstractQueuedSynchronizer

    protected final void setState(int newState) {        state = newState;    }


2. When the tryAcquire method is called, The nonfairTryAcquireShared method of NonfairSync is actually called. nonfairTryAcquireShared is implemented in the parent Sync class,

Semaphore # tryAcquire method:

    public boolean tryAcquire() {        return sync.nonfairTryAcquireShared(1) >= 0;    }

NonfairTryAcquireShared method of Sync

        final int nonfairTryAcquireShared(int acquires) {            for (;;) {                int available = getState();                int remaining = available - acquires;                if (remaining < 0 ||                    compareAndSetState(available, remaining))                    return remaining;            }        }

The nonfairTryAcquireShared method obtains the current state, and this state minus the number of semaphores to be obtained. If the result is smaller than 0, the remaining number is returned. If the result is greater than or equal to 0, the value of state is set to the remaining number based on CAS, And the for loop is used in the current step. Therefore, the system exits only when the result is smaller than 0 or the state value is set successfully.

If the number of remaining licenses returned is greater than 0, the tryAcquire method returns true; otherwise, false is returned.


CompareAndSetState method of AbstractQueuedSynchronizer,

    protected final boolean compareAndSetState(int expect, int update) {        // See below for intrinsics setup to support this        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);    }

3. release a license using the release method

    public void release() {        sync.releaseShared(1);    }
The releaseShared method of AbstractQueuedSynchronizer,

    public final boolean releaseShared(int arg) {        if (tryReleaseShared(arg)) {            doReleaseShared();            return true;        }        return false;    }
The release method indirectly calls the tryReleaseShared method of Sync. This method sets the state value to state + 1 based on Cas, and continuously loops to ensure that the CAS operation is successful. true is returned after the operation is successful.

        protected final boolean tryReleaseShared(int releases) {            for (;;) {                int p = getState();                if (compareAndSetState(p, p + releases))                    return true;            }        }

According to the above analysis, we can see that Semaphore adopts CAS to avoid the use of locks and improve the performance.





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.