Java multithread Read and write lock Reentrantreadwritelock principle of detailed __java

Source: Internet
Author: User
Tags cas

Reentrantlock are exclusive locks that allow only one thread to access at the same time, while read-write locks allow multiple threads to access at the same time, but all read and other write threads are blocked while the write thread is accessing. Read and write locks maintain a pair of locks, a read lock and a write lock, through the separation of read locks and write locks, so that concurrency compared to the general exclusive lock has a great improvement.
Now let's take a look at the read-write lock Reentrantreadwriter feature
Fair choice: support for unfair (default) and fair lock acquisition mode, throughput or unfairness better than fair
Reentrant : This lock supports reentrant locks, as in the case of read-write threads: The read thread can read the lock again after acquiring the read lock, and the write thread can acquire the read lock and write lock again after acquiring the write lock
Lock demotion: follow get write lock, get read lock and Release write lock order, write lock can degrade to read lock reading and writing lock interface

Reentrantreadwriterlock is the Readwriterlock interface implementation class, but the Readwriterlock interface has only read-lock, write-lock two methods

/** @see reentrantreadwritelock
 * @see Lock
 * @see reentrantlock * *
 @since 1.5
 * @author Doug Lea
  */Public
interface Readwritelock {
    /**
     * Returns the lock used for reading.
     *
     * @return The lock used for reading.
     * *
    Lock readlock ();
    /**
     * Returns the lock used for writing.
     *
     * @return The lock used for writing.
     * *
    Lock writelock ();
}

The

Reentrantreadwriterlock itself provides some internal working state methods, such as

     /** * Returns the number of times the current read lock was fetched, which is not equal to the number of threads acquiring the lock, because the same thread can obtain the support reentrant lock multiple times * Queries the number of read locks held for this lock.
     This * "is" is designed to use the monitoring System state and not to * synchronization control.
     * @return The number of read locks held.
    * * public int getreadlockcount () {return sync.getreadlockcount ();
        /** * * Returns the number of times the current thread acquires a read lock, JAVA6 uses threadlocal to save the number of times the current thread has been fetched * * Final int getreadholdcount () {
        if (getreadlockcount () = = 0) return 0;
        Thread current = Thread.CurrentThread ();
        if (Firstreader = = current) return firstreaderholdcount;
        Holdcounter RH = Cachedholdcounter;
        if (RH!= null && Rh.tid = = Current.getid ()) return rh.count;
        int count = Readholds.get (). Count;
        if (count = = 0) readholds.remove ();
    return count; /** * To determine whether the write lock was acquired * @author Fuyuwei * May 21, 2017 morning 11:04:01 * @retuRN/FINAL Boolean iswritelocked () {return Exclusivecount (GetState ())!= 0; /** * To determine the number of times the current write lock was fetched * @author Fuyuwei * May 21, 2017 morning 11:05:05 * * @return * * Final int get
    Writeholdcount () {return isheldexclusively () Exclusivecount (GetState ()): 0; }

Let's take a look at a caching example to illustrate the use of a read-write lock

public class Cache {
    static map<string,object> Map = new hashmap<string,object> ();
    static Reentrantreadwritelock rwl = new Reentrantreadwritelock ();
    static Lock R = Rwl.readlock ();
    static Lock W = Rwl.writelock ();

    public static final Object get (String key) {
        r.lock ();
        try {return
            map.get (key);
        } finally {
            r.unlock ();

    }} public static final Object put (String key,string value) {
        w.lock ();
        try{return
            map.put (key, value);
        } finally{
            W.unlock ();
        }

    public static final void clear () {
        w.lock ();
        try{
            map.clear ();
        } finally{
            W.unlock ();}}

The above hashmap is not thread safe, but we use read and write locks separately in get and put, which ensures thread safety, where write locks support concurrent access. The realization principle analysis of Read-write lock design of Read and write state

The read-write lock also relies on a custom Synchronizer to implement the synchronization function, while the read-write state is the sync state of its synchronizer. Recall the implementation of the custom Synchronizer in Reentrantlock, which indicates the number of times the lock was repeatedly fetched by one thread, while a custom synchronizer for read-write locks needs to maintain multiple read threads and a write-thread-like state on the synchronization status (an integer variable)
, which makes the design of this state the key to the realization of the read-write lock. If you maintain a variety of states on an integer variable, it is necessary to "cut using" this variable, read and write lock to cut the variable into two parts, high 16-bit read, low 16-bit writing, divided by the following figure

The current synchronization state indicates that a thread has acquired a write lock, has entered two times, and has acquired two read locks consecutively. How quickly read and write locks determine the state of reading and writing. The answer is through bit arithmetic. Assuming that the current sync state value is s, the Write state equals S&0X0000FFFF (16-bit high), and the Read state equals s>>>16 (unsigned 0 to right 16-bit). When the write state increases 1 o'clock, equals s+1, when the reading state increases 1 o'clock, equals s+ (1<<16), namely s+0x00010000. According to the Division of State can draw a conclusion: S not equal to 0 o'clock, when the write state (S&0X0000FFFF) is equal to 0 o'clock, the read state (S>>>16) is greater than 0, that is, read lock has been acquired. acquisition and release of write locks

A write lock is an exclusive lock that supports re-enter. If the current thread has acquired a write lock, the write state is added. If the current thread is fetching a write lock and the read lock has been fetched (the read state is not 0) or if the thread is not a thread that has acquired a write lock, the current thread enters the wait state, and we look at the Reentrantreadwritelock Tryacquire method

        Protected Final Boolean tryacquire (int acquires) {/* Walkthrough: * 1.
             If read count nonzero or write count nonzero * and owner is a different thread, fail. * 2. If count would saturate, fail.
             (This can only * happen if count is already nonzero.) * 3. Otherwise, this thread are eligible for lock if * either a reentrant acquire or * que UE policy allows it.
             If So, the update state * and set owner.
            * * Thread current = Thread.CurrentThread ();
            int c = GetState ();
            int w = Exclusivecount (c); if (c!= 0) {//(Note:if C!= 0 and w = 0 then shared count!= 0)//exists read lock or the current fetch thread is not already acquired
                The thread of the lock if (w = = 0 | | | current!= getexclusiveownerthread ()) return false; if (W + exclusivecount (acquires) > Max_count)
                    throw new Error ("Maximum lock count Exceeded");
                Reentrant acquire SetState (c + acquires);
            return true;
                } if (Writershouldblock () | |
            !compareandsetstate (c, C + acquires)) return false;
            Setexclusiveownerthread (current);
        return true; }

This method adds a judgment of whether a read lock exists except for the reentrant condition (the current thread is the thread that acquired the write lock). If there is a read lock, the write lock cannot be acquired because read-write locks make sure that the write-lock operation is visible to the read lock, and that other read threads that are running cannot perceive the operation of the current write thread if the read lock is allowed to acquire the write lock if it has been acquired. Therefore, only waiting for other read threads to release the read lock, the write lock can be acquired by the current thread, and once the write lock is fetched, subsequent access to other read-write threads is blocked. The release of the write lock is basically similar to the release process of the Reentrantlock, each release reduces the write state, when the write state is 0, the write lock has been released, so that the waiting read-write thread can continue to access the read and write lock, while the previous write-thread modification of the subsequent read-write thread

Read lock is a shared lock that supports re-enter, it can be acquired by multiple threads at the same time, when no other write thread access (or write state is 0), read lock will always be successfully acquired, and do only (thread safe) increase read state. If the current thread has acquired a read lock, the read state is increased. If the current thread acquires a read lock and the write lock is acquired by another thread, it enters the wait state. The implementation of acquiring read locks has become much more complex from Java 5 to Java 6, mainly because of new features such as the Getreadholdcount () method, which returns the number of times the current thread acquires a read lock. The read state is the sum of the number of read locks that are acquired by all threads, and the number of times each thread acquires a read lock can only be saved in threadlocal, maintained by the thread itself, which complicates the acquisition of the read lock

      Protected final int tryacquireshared (int unused) {* * Walkthrough: * 1.
             If write lock held by another thread, fail. * 2. Otherwise, this thread are eligible for * lock WRT state, so ask if it should block * Becau SE of queue policy.
             If not, try * to grant by casing state and updating count.
             * Note This step does not check for reentrant * acquires, which are postponed to full version
             * To avoid has to check hold count in * The more typical non-reentrant case. * 3. If Step 2 fails either because thread * apparently not eligible or CAS fails or count * SA
             Turated, chain to version with the full retry loop.
            * * Thread current = Thread.CurrentThread ();
            int c = GetState (); if (Exclusivecount (c)!= 0 && GetexclusivEownerthread ()!= current) return-1;
            int r = Sharedcount (c); if (!readershouldblock () && R < Max_count && Compareandsetstate (c, C +
                    Shared_unit)) {if (r = = 0) {Firstreader = current;
                Firstreaderholdcount = 1;
                else if (Firstreader = = current) {firstreaderholdcount++;
                    else {holdcounter RH = Cachedholdcounter;
                    if (RH = NULL | | Rh.tid!= current.getid ()) Cachedholdcounter = RH = Readholds.get ();
                    else if (rh.count = 0) readholds.set (RH);
                rh.count++;
            return 1;
        Return to fulltryacquireshared (current); }

In the tryacquireshared (int unused) method, if another thread has acquired a write lock, the current thread acquires the read lock failure and enters the wait state. If the current thread acquires a write lock or the write lock has not been fetched, the current thread (thread-safe, relying on the CAS guarantee) increases the read state and succeeds in acquiring the read lock. Each release of the read lock (thread-safe, possibly with multiple read threads releasing read locks at the same time) reduces the read state, and the reduced value is (1<<16) lock demotion

Lock demotion refers to a write lock demotion into a read lock. If the current thread has a write lock, then releases it, and then acquires a read lock, the process of completing this subsection cannot be called a lock demotion. Lock demotion refers to the process of holding (the currently owned) write locks, acquiring to read locks, and then releasing (previously owned) write locks.

public void ProcessData () {
        readlock.lock ();
        if (!update) {
            //must first release read lock
            Readlock.unlock ();
            Lock demotion from write lock fetch to start
            writelock.lock ();
            try {
                if (!update) {
                    //Prepare Data Flow (abbreviated)
                    update = true;
                }
                Readlock.lock ();
            } finally {
                writelock.unlock ();
            } Lock demotion complete, write lock degraded to read lock
        }
        try {//process using data (abbreviated)
        } finally {
            readlock.unlock ()
    }}

In the preceding example, when the data changes, the update variable (the Boolean type and the volatile modifier) is set to false, at which point all threads accessing the ProcessData () method can perceive the change, but only one thread can acquire the write lock. Other threads are blocked on the lock () method of Read and write locks. The current thread acquires the write lock to complete the data preparation, then acquires the read lock, then releases the write lock and completes the lock demotion. Lock demotion first Acquire write lock in order to ensure thread safety, if the write lock is freed at this time other threads write I may not be reading the latest data in acquiring read locks.

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.