Java concurrent Programming--abstractqueuedsynchronizer lock and Lock Analysis (ii) __java

Source: Internet
Author: User

There are many implementation classes of lock in the Java.util.concurrent.locks package, commonly used in Reentrantlock, Readwritelock (Implementation class Reentrantreadwritelock), Its realization all relies on Java.util.concurrent.AbstractQueuedSynchronizer class, realizes the idea to be similar, therefore we take reentrantlock as the explanation cut-in point. 1. Reentrantlock's call Process

After observation Reentrantlock all lock interface operations are delegated to a sync class, the class inherits the Abstractqueuedsynchronizer:

Java code static abstract class Sync extends Abstractqueuedsynchronizer

Sync has two subclasses: Java code final static class Nonfairsync extends sync Java code final static class Fairsync extends Sync

It is clearly defined to support fair and unjust locks, which are not fair by default.

First, take a look at the call procedure for the Reentrant.lock () method (default non-fair lock):


These pesky template patterns make it hard to see the entire calling process visually, and in fact, through the above invocation process and the Abstractqueuedsynchronizer annotation, Most lock functions are abstracted in Abstractqueuedsynchronizer, and only the Tryacquire method is deferred to the subclass. The semantics of the Tryacquire method is to determine whether a request thread can acquire a lock with a specific subclass, regardless of success or failure, Abstractqueuedsynchronizer will process the following process. 2. Lock implementation (LOCK)

Simply put, Abstractqueuedsynchronizer will make all the request threads into a CLH queue, activating its successor when one thread completes (Lock.unlock ()), but the executing thread is not in the queue, While those waiting to execute are all in a blocking state, the explicit blocking of the investigated thread is done by calling Locksupport.park (), while Locksupport.park () calls the Sun.misc.Unsafe.park () local method, and further, Hotspot in Linux by calling the Pthread_mutex_lock function to block the thread to the system kernel.

The queue is shown in figure:


As with synchronized, this is also a virtual queue, there is no queue instance, and there is only a relationship between nodes. It is doubtful why the CLH queue is used. The native CLH queue was used for spin locks, but Doug Lea transformed it into a blocking lock.

When a thread competes for a lock, the line Cheng first attempts to acquire the lock, which is unfair to those already queued in the queue, which is also the origin of the unjust lock, similar to the synchronized implementation, which greatly improves throughput.

If a running thread already exists, the new competitive thread is appended to the tail, in particular the CAS based Lock-free algorithm, because the thread concurrent to the tail call CAs may cause other thread CAs to fail, and the solution is to cycle the CAS until successful. The implementation of the Abstractqueuedsynchronizer is very sophisticated, breathtaking, the details are difficult to fully understand its essence, the following detailed description of the implementation process:

2.1 Nonfairsync.lock

Java Code/** * performs lock.   Try immediate barge, backing up to normal * acquire on failure. /final void Lock () {//If the lock is not locked by any thread and the lock succeeds, set the current thread to be the owner of the lock//If the lock is locked by the current thread, add 1 in Acquire and return if (compare       Andsetstate (0, 1)) Setexclusiveownerthread (Thread.CurrentThread ());   else//Lock fails, attempts to lock again, fails to join the wait queue, disables the current thread until it is awakened acquire (1) when it is interrupted or the wire releases the lock; }

2.2 Sync.nonfairtryacquire

The Nonfairtryacquire method will be the first method indirectly invoked by the lock method, which is invoked each time the lock is requested. Java Code   /**           * performs non-fair  tryLock.  tryAcquire is           *  implemented in subclasses, but both need nonfair            * try for trylock method.            */           final  Boolean nonfairtryacquire (int acquires)  {                final thread current = thread.currentthread ();               int c = getstate ();    &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&Nbsp; if  (c == 0)  {                    //  if lock is idle try to lock, success set current thread as lock owner                     if  (Compareandsetstate (0,  Acquires))  {                        setexclusiveownerthread (current);                        return  true;                    }               }               //  Modify the Lock status count directly if the current thread is the lock owner     &NBSP;&NBSP;&NBSp;         else if  (current ==  Getexclusiveownerthread ())  {                    int nextc = c + acquires;                    if  (nextc <  0)  // overflow                        throw new error ("Maximum lock count  exceeded ");                    setstate (NEXTC);                    return true;                } &nbsp             //  try to get failed, return                 return false;            }  

The method first determines the current state, if c==0 indicates that there is no line one thread in the competition for the lock, if no C!=0 indicates that the thread is owning the lock.

1. If c==0 is found, the initial call value of Acquires,acquires is set to 1 through CAs, and if the CAS setting succeeds, it can be expected that any other thread to call CAS will not succeed again, and that the current thread has the lock as well as the running thread. Obviously this running thread does not enter the wait queue.

2. If C!=0 but finds that he already owns the lock, simply recalculates the status + acquires and modifies the status value, but because there is no competition, it is modified by setstatus instead of CAs, which means that this code implements a lock-biased function, And it's very nice to realize. Each time a thread resets the lock, it will be +1, each time unlock-1, but the lock is released for 0 o'clock. 2.3 Abstractqueuedsynchronizer.addwaiter

The Addwaiter method is responsible for wrapping a thread that is currently unable to acquire a lock as a node to add to the team tail: Java code

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.