"Dead java Concurrency"-----j.u.c Lock: Reentrantlock

Source: Internet
Author: User

All source code for this blog is from JDK 1.8

Reentrantlock, can be re-entered lock, is a recursive non-blocking synchronization mechanism. It can be equated to the use of synchronized, but Reentrantlock provides a more powerful and flexible locking mechanism than synchronized, which reduces the probability of deadlocks.
The API is described below:

A reentrant mutex lock lock, which has the same basic behavior and semantics as the implicit monitor lock accessed using the Synchronized method and the statement, but is more powerful. Reentrantlock will be owned by a thread that has recently successfully acquired a lock and has not released the lock. When the lock is not owned by another thread, the thread that called lock succeeds in acquiring the lock and returns. If the current thread already owns the lock, this method will return immediately. You can use the Isheldbycurrentthread () and Getholdcount () methods to check whether this condition occurs.

Reentrantlock also offers the option of fair lock and unfair lock, the construction method accepts an optional fairness parameter (default unfair lock), when set to True, represents a fair lock, otherwise an unfair lock. The difference between a fair lock and a non-fair lock is that the lock acquisition of a fair lock is sequential. But the efficiency of the fair lock is often not as high as the non-fair lock, and in the case of many threads access, the fair lock shows a lower throughput.

Get lock

We generally use reentrantlock to get locks:

//非公平锁new ReentrantLock();lock.lock();

Lock method:

    publicvoidlock() {        sync.lock();    }

Sync is an inner class inside Reentrantlock, which inherits Aqs (Abstractqueuedsynchronizer), which has two subcategories: Fair lock fairsync and non-fair lock nonfairsync.

Reentrantlock most of the functions are delegated to sync to achieve, and sync internally defines the lock () abstract method is implemented by its subclasses, the default implementation of the Nonfairtryacquire (int acquires) method, You can see that it is the default implementation of an unfair lock. Below we look at the lock () method of the unfair lock:

    finalvoid lock() {        //尝试获取锁        if (compareAndSetState(01))            setExclusiveOwnerThread(Thread.currentThread());        else            //获取失败,调用AQS的acquire(int arg)方法            acquire(1);    }

The first attempt is to quickly acquire the lock, and if it fails, call the acquire (int arg) method, which is defined in Aqs as follows:

    publicfinalvoidacquire(int arg) {        if (!tryAcquire(arg) &&                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))            selfInterrupt();    }

This method first calls the Tryacquire (int arg) method, as described in Aqs, tryacquire (int arg) requires a custom synchronization component to provide the implementation, and the non-fair lock implementation is as follows:

    protected Final Boolean Tryacquire(intAcquires) {returnNonfairtryacquire (acquires); }Final BooleanNonfairtryacquire (intAcquires) {//When the front-line        FinalThread current = Thread.CurrentThread ();//Get sync status        intc = GetState ();//state = = 0, indicating that the lock is not in an idle state        if(c = =0) {//Get lock succeeded, set to current thread all            if(Compareandsetstate (0, acquires)) {Setexclusiveownerthread (current);return true; }        }//Thread re-entry        //Determines whether the thread held by the lock is the current thread        Else if(Current = = Getexclusiveownerthread ()) {intNEXTC = c + acquires;if(NEXTC <0)//Overflow                Throw NewError ("Maximum lock count Exceeded"); SetState (NEXTC);return true; }return false; }

The main logic of the method: first of all to determine the synchronization status state = = 0, if it means that the lock has not been held by the thread, directly through the CAs to obtain the synchronization state, if successful return true. If state! = 0, determines whether the current thread is the thread that acquires the lock, and if it is, gets the lock and returns true successfully. The thread that successfully acquires the lock acquires the lock again, which is the state that added the synchronization status.

Release lock

After the sync lock is acquired, the lock is released when it is finished, and the Reentrantlock provides a unlock release lock:

    publicvoidunlock() {        sync.release(1);    }

Unlock internally uses the release (int arg) of sync to free the lock, and release (int arg) is defined in the AQS:

    publicfinalbooleanrelease(int arg) {        if (tryRelease(arg)) {            Node h = head;            ifnull0)                unparkSuccessor(h);            returntrue;        }        returnfalse;    }

Similar to the acquire (int arg) method that gets the synchronization state, tryrelease (int arg) that releases the synchronization state also needs to be implemented by the custom synchronization component itself:

    protected Final Boolean Tryrelease(intReleases) {//Lose releases        intc = getState ()-releases;//If you are releasing a thread that is not holding a lock, throw an exception        if(Thread.CurrentThread ()! = Getexclusiveownerthread ())Throw NewIllegalmonitorstateexception ();BooleanFree =false;//state = = 0 means that the release is complete and the other threads can get the synchronization status.        if(c = =0) {free =true; Setexclusiveownerthread (NULL); } setState (c);returnFree }

The method returns true only if the synchronization state is completely released. When state = = 0 o'clock, the lock holding thread is set to null,free= true to indicate that the release was successful.

Fair lock and non-fair lock

The difference between a fair lock and a non-fair lock is whether the lock is acquired in the order of FIFO. There is no fairness or unfairness in releasing the lock, as an example of an unfair lock above, let's look at the tryacquire (int arg) of the Fair Lock:

    protected Final Boolean Tryacquire(intAcquires) {FinalThread current = Thread.CurrentThread ();intc = GetState ();if(c = =0) {if(!hasqueuedpredecessors () && compareandsetstate (0, acquires)) {Setexclusiveownerthread (current);return true; }        }Else if(Current = = Getexclusiveownerthread ()) {intNEXTC = c + acquires;if(NEXTC <0)Throw NewError ("Maximum lock count Exceeded"); SetState (NEXTC);return true; }return false; }

Comparing the process of the unfair lock and the fair lock to get the synchronization state, the only difference between the two is that the fair lock has one more restriction condition when acquiring the synchronization state: Hasqueuedpredecessors (), as defined below:

    publicfinalbooleanhasQueuedPredecessors() {        Node t = tail;  //尾节点        Node h = head;  //头节点        Node s;        //头节点 != 尾节点        //同步队列第一个节点不为null        //当前线程是同步队列第一个节点        return h != t &&                null || s.thread != Thread.currentThread());    }

The main thing to do in this approach is to determine whether the current thread is the first in the CLH synchronization queue. Returns true if yes, otherwise false.

The difference between Reentrantlock and synchronized

The previous mention of Reentrantlock provides a more flexible and powerful locking mechanism than synchronized, so where is its flexibility and power? What is the difference between them?

First they must have the same functionality and memory semantics.

    1. Compared with synchronized, Reentrantlock offers more, more comprehensive functionality with greater scalability. For example: Time lock waiting, can interrupt lock wait, lock vote.
    2. Reentrantlock also provides conditional condition, which is more detailed and flexible for thread waits, wake-up operations, so reentrantlock is more suitable where multiple condition variables and highly competitive locks are available (condition will be elaborated later).
    3. The Reentrantlock provides a lock request that can be polled. It will try to get the lock, if successful continue, otherwise you can wait for the next run time processing, and synchronized once the lock request is either successful or blocked, so compared to synchronized, Reentrantlock will not be easy to create deadlock.
    4. The Reentrantlock supports more flexible synchronization blocks, but when synchronized is used, it can only be obtained and freed in the same synchronized block structure. Note: The lock release of Reentrantlock must be handled in the finally, otherwise it may have serious consequences.
    5. Reentrantlock supports interrupt handling, and performance is better than synchronized.
Recommended Reading

There are many ways to get the lock, release the lock process is a combination of the methods in the Aqs, as the basis of the synchronization component, Aqs do too much work, custom synchronization components simply to implement a custom method, and then add Aqs provided template method, you can implement a powerful custom synchronization components, So after reading the following four blog posts, Reentrantlock is really a piece of cake to understand.

    1. A brief introduction to the Aqs:aqs of "-–j.u.c java concurrency"
    2. "Dead java Concurrency"-–j.u.c aqs:clh synchronization queue
    3. "Dead java Concurrency"-–J.U.C's AQS: Acquisition and release of synchronization state
    4. "Dead java Concurrency"-–j.u.c Aqs: Blocking and waking threads
Resources
    1. Doug Lea: "Java Concurrency Programming Combat"
    2. Fang Fei: "The Art of Java concurrent programming"

"Dead java Concurrency"-----j.u.c Lock: Reentrantlock

Related Article

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.