Talk about high concurrency (25) Parsing java.util.concurrent Components (vii) Understanding Semaphore

Source: Internet
Author: User
Tags ticket

The previous several analyzed the AQS principle and the realization, this article takes semaphore the signal quantity to do the example to see Aqs actually how uses.


Semaphore represents a synchronizer that can simultaneously have multiple threads entering the critical section, which maintains a status indicating the available tickets, and only the thread that gets the ticket can enter the critical section, otherwise wait until the released ticket is obtained. Semaphore are often used in resource pools to manage resources. When the state has only 1 2 values, it degenerates into a mutex, similar to a lock.


Let's look at the code for semaphore.

It maintains an internal class sync to inherit Aqs, customizing the Tryxxx method to use Aqs. We mentioned earlier that AQS supports both exclusive and shared modes, and semaphore is obviously a shared mode, which enables multiple threads to enter the critical section at the same time. So sync extends the method associated with GKFX.

You can see that sync's primary operation is a lock-free modification of the state, and it does not need to handle AQS queue-related operations. Talking about high concurrency (24) Parsing java.util.concurrent components (vi) in-depth understanding of Aqs (iv ) We said AQS provides a tryxxx interface to the subclass extension, which is equivalent to giving the subclass an opportunity to handle the state on its own, Determines whether to enter the synchronization queue.

1. nonfailtryacquireshared () unfair tryacquire, which immediately modifies the state of the ticket without having to wait for a first-come thread, and once there is a ticket available, the lock is obtained directly, without the need to enter AQS queue for synchronization.

2. The tryreleaseshared () method is responsible for releasing the shared state of the resource, which only modifies the ticket state, and is responsible for waking the thread waiting in the Aqs queue by the Aqs releaseshared () method

3. The reducepermits () and Drainpermits () methods are directly modifying the state to limit the available resources

Abstract static class Sync extends Abstractqueuedsynchronizer {private static final long Serialversionuid = 119245        7210091910933L;        Sync (int permits) {setState (permits);        } final int getpermits () {return getState (); } final int nonfairtryacquireshared (int acquires) {for (;;)                {int available = GetState ();                int remaining = Available-acquires;                    if (Remaining < 0 | |            Compareandsetstate (available, remaining)) return remaining; }} 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");            if (Compareandsetstate (current, next)) return true; }       } 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; }} final int drainpermits () {for (;;)                {int current = GetState ();            if (current = = 0 | | compareandsetstate (current, 0)) return to current; }        }    }

Sync is also an abstract class, the specific implementation is nonfailsync and Fairsync, representing the non-fair realization and fair realization. As mentioned in the previous article, the so-called unfairness simply says that when a resource is fetched, it is possible to make a subsequent thread that does not need the first-come thread in the AQS queue to fetch the resource, and once it fails, it has to go into the Aqs queue, and the Aqs queue is the FIFO queue that comes first to serve.

As you can see, Nonfailsync and Fairsync are just different from the implementation of the Tryacquireshared method, the others are the same.

/** * Nonfair version */static final class Nonfairsync extends Sync {private static final long Serialv        Ersionuid = -2694183684443567898l;        Nonfairsync (int permits) {super (permits);        } protected int tryacquireshared (int acquires) {return nonfairtryacquireshared (acquires); }}/** * Fair version */static final class Fairsync extends Sync {private static final long ser        Ialversionuid = 2014338818796000944L;        Fairsync (int permits) {super (permits); } protected int tryacquireshared (int acquires) {for (;;)                {if (hasqueuedpredecessors ()) return-1;                int available = GetState ();                int remaining = Available-acquires;                    if (Remaining < 0 | |            Compareandsetstate (available, remaining)) return remaining; }        }    }

Take a look at Semaphore's own approach,

1. Support for interruptible and non-disruptive access/release

2. Support Time-limited access

3. Support TRYXX Acquisition/release

4. Support simultaneous acquisition/release of multiple resources


You can see that the implementation of Semaphore is based on the Aqs method, the acquisition/release of a single resource is requested 1 resources, so the parameter is passed 1, multiple resource gets passed an int number.

public void Acquire () throws Interruptedexception {sync.acquiresharedinterruptibly (1); }public void acquireuninterruptibly () {        sync.acquireshared (1);    }public boolean tryacquire () {        return Sync.nonfairtryacquireshared (1) >= 0;   }public boolean tryacquire (long timeout, timeunit unit)         throws Interruptedexception {         Return Sync.tryacquiresharednanos (1, Unit.tonanos (timeout));   }public void release () { & nbsp;      sync.releaseshared (1);   }public void Acquire (int permits) Throws Interruptedexception {        if (permits < 0) throw new IllegalArgumentException ();        sync.acquiresharedinterruptibly (permits);    }public void Acquireuninterruptibly (int permits) {        if (permits < 0) throw new IllegalArgumentException ();        sync.acquireshared (permits);    }public boolean tryacquire (int permits) {        if (permits < 0) throw new I Llegalargumentexception ();        return sync.nonfairtryacquireshared (permits ) >= 0;   }public boolean tryacquire (int permits, long timeout, timeunit unit)          throws Interruptedexception {        if (permits < 0) throw new IllegalArgumentException ();        return Sync.tryacquiresharednanos ( Permits, Unit.tonanos (timeout));   }public void release (int permits) {         if (permits < 0) throw new IllegalArgumentException ();        sync.releaseshared (permits);   } 

Here is an example to test the function of semaphore.

1. Create a semaphore with two notes

2. Create 20 threads to compete for execution of the race () method

3. In the race () method to print a sentence to wait for the resource, then get the resources, get the resources to print a word, finally release resources, release resources before printing a word

Package Com.lock.test;import Java.util.concurrent.semaphore;public class Semaphoreusecase {private Semaphore semaphore = new Semaphore (2);p ublic void Race () {System.out.println ("Thread" + thread.currentthread (). GetName () + "is Wai Ting the resource "); semaphore.acquireuninterruptibly (); Try{system.out.println (" Thread "+ thread.currentthread (). GetName () + "got the Resource"); try {thread.sleep);} catch (Interruptedexception e) {e.printstacktrace ();}} Finally{system.out.println ("Thread" + thread.currentthread (). GetName () + "is releasing the resource"); Semaphore.release ();}} public static void Main (string[] args) {final semaphoreusecase usecase = new Semaphoreusecase (), for (int i = 0; i <; I + +) {thread t = new Thread (new Runnable () {@Overridepublic void run () {Usecase.race ()}}, String.valueof (i)); T.start ();}}}

Test results:

You can see the first two lines enters upgradeable get the resources, and then the threads are waiting, when the thread frees the resources, the waiting threads will get the resources until they get/release the resources.

Thread 0 is waiting the Resourcethread 0 got the Resourcethread 2 is waiting the Resourcethread 2 got the Resourcethread 1 Is waiting the Resourcethread 4 is waiting the Resourcethread 3 are waiting the Resourcethread 5 is waiting the Resourceth Read 6 is waiting the Resourcethread 7 is waiting the Resourcethread 8 are waiting the Resourcethread 9 is waiting the Reso Urcethread 2 is releasing the Resourcethread 0 is releasing the Resourcethread 1 got the Resourcethread 4 got the resource Thread 1 is releasing the Resourcethread 4 is releasing the Resourcethread 3 got the Resourcethread 5 got the Resourcethre  Ad 3 is releasing the Resourcethread 5 is releasing the Resourcethread 6 got the Resourcethread 7 got the Resourcethread 7 Is releasing the Resourcethread 6 are releasing the Resourcethread 8 got the Resourcethread 9 got the Resourcethread 8 is Releasing the Resourcethread 9 is releasing the resource








Talk about high concurrency (25) Parsing java.util.concurrent Components (vii) Understanding Semaphore

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.