Java.util.concurrent.locks.ReentrantReadWriteLock read-write lock source analysis _______1.1.2

Source: Internet
Author: User
Tags static class
1. What is read and write lock

It is possible to allow multiple read threads to access at the same time, or locks that are blocked by all read threads and other write threads when the write thread is accessed. Read-write lock in two, divided into a read lock and a write lock, through the separation of read and write locks, so that concurrency compared to the general exclusive lock has been promoted. 2. Read and write lock ownership package

Package java.util.concurrent.locks;

3. Read-write lock inheritance and implementation relationship

public class Reentrantreadwritelock
        

4. Read-write lock custom synchronizer source code

to customize the implementation class for the Synchronizer :

Abstract static class Sync extends Abstractqueuedsynchronizer


key variables and methods for customizing the Synchronizer :

Shifted offset constant static final int shared_shift = 16;
		
* Read lock increased order of magnitude * read lock use high 16 bits * So read lock increase of 1 is equivalent to increase the 2*16 * * static final int shared_unit = (1 << shared_shift);
		
/* Write lock Maximum number of reentrant * Read lock allowed maximum number of * * static final int max_count = (1 << shared_shift)-1;
		
* * Write Lock Mask * Write lock use low 16 bits * This mask for easy and operation remove high 16 bits/static final int exclusive_mask = (1 << shared_shift)-1;
		
/** * Saves the number of Reentrant read locks held by the current thread, and removes the */private transient threadlocalholdcounter readholds when the read lock is reset to 0 times;
 /* The last count of a thread that successfully acquired a read lock.
		
* * Private transient holdcounter cachedholdcounter;
 /* Firstreader is the last thread to change the shared count from 0 to 1 when the lock is idle, and the read lock has not been released since then.
 * NULL if it does not exist.
		
* Private transient Thread firstreader = null;
 * * Firstreaderholdcount is the firstreader count of the.
		
* Private transient int firstreaderholdcount;

Number of threads currently holding read locks static int sharedcount (int c) {return C >>> shared_shift;}

Count of write lock reentrant number static int exclusivecount (int c) {return C & exclusive_mask;} /** * Count of reads per thread * Cached in Holdcounter/sTatic Final class Holdcounter {int count = 0;
Use ID, not reference, to avoid garbage retention final long tid = Thread.CurrentThread (). GetId (); /** * Initialize Holdercounter * Returns the value of the local variable initialized by each thread * * Static final class Threadlocalholdcounter extends Threadlocal 

How to implement a custom Synchronizer :

Tryrelease () Method: Allow it to release lock resources in exclusive mode

 /* Allow it to release the lock resource in exclusive mode
/protected Final Boolean tryrelease (int releases) {
	//If the current thread is not in an exclusive manner, Throws an exception
        if (!isheldexclusively ())
             throw new Illegalmonitorstateexception ();
	Calculates the latest sync state value
        int nextc = GetState ()-releases;
	Whether the number of write lock reentrant counts is 0, which is whether the thread is already in the initialization state.
        Boolean free = Exclusivecount (NEXTC) = = 0;
	If free is true, the current thread is already in the initialized state if
        (free)
	    //Set the thread with exclusive access to null
            setexclusiveownerthread (NULL);
	Atomic mode updates the latest synchronization state value
        SetState (NEXTC);
        return free;
}
Step resolution:

(1) First to determine whether the current thread is exclusive, to calculate the latest synchronization state value.

(2) If the operation is exclusive, then the number of write locks can be calculated by the most recent synchronization state values calculated before.

(3) If the current thread is in the initialization state, setting the exclusive access thread does not exist as null. Updates the most recent sync state values in atomic mode.

Tryrelease Flowchart:



Tryacquire () Method: Allow it to get sync State in exclusive mode

Do you want to allow it to get object state in exclusive mode
protected final Boolean tryacquire (int acquires) {
        //get current threads thread present
        = Thread.CurrentThread ();
	Gets the current sync state
        int c = getState ();
	Gets the number of write lock reentrant
        int w = Exclusivecount (c);
	If the current sync state is not an initialization state if
        (C!= 0) {
             //If the number of writes is 0, or if the thread is not an exclusive access, return False if
             (w = 0 | | | current!= Getexclusi Veownerthread ()) return
                  false;
	     Throws an exception if
             (W + exclusivecount (acquires) > Max_count) throw new Error If the number of writeback attempts and the current thread request gets a write-back number greater than the maximum write-back number
                  ( "Maximum lock count Exceeded");
             The atomic way sets the new sync state value
             SetState (c + acquires);
             return true;
         }
	 If the current thread attempts to acquire a write lock or the current sync state value is not equal to C, return False if
         (writershouldblock) | |
                ! Compareandsetstate (c, C + acquires)) return
             false;
	 Sets the thread that has exclusive access to the current thread
         setexclusiveownerthread.
         return true;
}
Step resolution:

(1) If the current synchronization state is not an initialization state, then the atomic way updates the sync state value.

(2) returns false if the current attempt is to acquire a write lock or the sync state value is not the most recent synchronization state value. ( write locks are mutually exclusive, there is already a write lock, and if a thread attempts to acquire a write lock, the problem of atomicity and consistency is not guaranteed ).

(3) The thread that sets exclusive access is the current thread, and returns True.

Tryacquire Flowchart:



Tryreleaseshared () Method:

Do you want to allow it to release the lock resource in shared mode protected final Boolean tryreleaseshared (int unused) {//Get current thread threads present = Thread.curr
     Entthread (); 
		If the current thread is the first read thread if (Firstreader = =) {//If the first read thread counts as 1 if (Firstreaderholdcount = 1)
           Sets the read thread to null firstreader = NULL;
      else//Otherwise the read thread count is reduced by one firstreaderholdcount--;
           else {//Gets the count of the most recent thread that successfully acquired a read lock.
	   Holdcounter RH = Cachedholdcounter;
                 If the last thread that successfully acquires a read lock has a count of NULL or the thread is not the current thread if (RH = NULL | | Rh.tid!= current.getid ())//assignment number of read locks held by the current thread
	   RH = Readholds.get ();
	   Gets the number of read locks held by the current thread int count = Rh.count;
                If the number of read locks is less than or equal to 1, the read lock held by the current thread is removed if (count <= 1) {readholds.remove ();
           if (count <= 0) throw unmatchedunlockexception ();
      }--rh.count; }//Dead loop for (;;)
	  {//Atomic mode gets the current sync state int c = GetState (); MillionsCalculates the newest synchronization state value int nextc = C-shared_unit;
               If the current thread's sync state value is equal to C, the current thread's sync state value is updated to NEXTC if (Compareandsetstate (c, NEXTC))/The latest sync state value is 0, which indicates that the shared release was successful
      return NEXTC = = 0; }
}
Step resolution:

(1) First to see if the current thread is the first to get the read lock thread, if the first to get read lock thread count is 1, then the current thread, the first to get read lock thread set to NULL, otherwise the count will be reduced by 1.

(2) If the current thread is not the first thread to acquire a read lock, gets the most recent thread that successfully acquired a read lock, if NULL or not the current thread, assigns the number of reentrant locks to the most recent thread that successfully acquired the read lock, and then the number of times the lock is reset by 1.

(3) Dead loop +cas mode to set the latest sync state.


Trywritelock () Method:

/**
  * Whether to allow attempt to acquire write lock/
final Boolean trywritelock () {
	//get current threads thread present
        = Thread.CurrentThread ();
	Atomic way to get synchronous state
        int c = getState ();
	If the current sync state is not an initialization state if
        (C!= 0) {
		//Gets the number of thread write lock reentrant
                int w = Exclusivecount (c);
		Returns False if
                (w = = 0 | | |!= getexclusiveownerthread ()) return False if the number of times the write lock has been reset is 0 or the thread that has exclusive access is not the current thread
                    ;
		If the number of times the write lock is reset equals the maximum number of times, throw the exception if
                (w = = Max_count)
                    throw new Error ("Maximum lock COUNT exceeded");
	Returns False if
        (!compareandsetstate (c, C, + 1)) return False if the current thread's sync state is not C
                ;
	Sets the thread that has exclusive access to the current thread
        setexclusiveownerthread.
        return true;
}
Step resolution:

(1) If the current synchronization state is not an initialization state, gets the number of write lock reentrant, if 0 or not the current thread (write lock mutex), returns false, and throws an exception if it is greater than the maximum value.

(2) returns False if the current synchronization state is not a obtained sync state.

(3) Set the thread with exclusive access to the current thread.

Trywritelock Flowchart:



Tryreadlock () Method: whether to allow attempts to acquire read locks

/** * Whether to allow attempts to acquire read lock/FINAL Boolean tryreadlock () {//Get current thread threads present = Thread.CurrentThread (); Dead loop for (;;)
	     {//Atomic way get sync state int c = GetState (); Returns False if (Exclusivecount (c)!= 0 && Getexclusiv If the number of write locks is not more than 0 and the permission for the exclusive access thread is not the current thread.
	     Eownerthread ()!= current) return false;
	     Gets the number of threads that read the lock int r = Sharedcount (c);
	     If the number of threads reading the lock equals the maximum number, throw the exception if (r = = max_count) throw new Error ("Maximum lock COUNT exceeded");
                 If the current sync state is C, update the current synchronization status to C+shared_unit if (Compareandsetstate (c, C, Shared_unit)) {//If the number of threads read Locks is 0
		      if (r = = 0) {//Set the first read thread firstreader = current;
                 The read thread holds a count of 1 firstreaderholdcount = 1;
            else if (Firstreader = = current) {//If the first read thread adds 1 firstreaderholdcount++ to the count of the thread//first read thread;     else {//The nearest counter of a thread that successfully acquired a read lock holdcounter RH = Cachedholdcounter; If the counter is null or the thread of the counter is not the current thread if (RH = NULL | | Rh.tid!= current.getid ())//The most recent thread counter that successfully acquired the read lock is set to
                      Pre-read counter Cachedholdcounter = RH = Readholds.get ();
		      else if (rh.count = 0)//If the count of the read counter is 0//Set Read counter Readholds.set (RH);
                 Read counter count plus 1 rh.count++;
             return true; }
        }
}
Step resolution:

(1) returns False if the number of write locks is not 0, and the current thread does not have exclusive access.

(2) If the current synchronization status is C: If the number of read threads is 0, the first read thread is set to the current thread, the read thread count is 1, and if the first read thread is the current thread, the Count plus 1 or the counter of the most recent thread that successfully acquires the read lock is removed. To determine whether or not the current thread is NULL, reset the counter for the most recent thread that successfully acquired the read lock, and determine if the counter has a count of 0, set the Read counter. Finally read the Counter plus 1.

(3) If the current synchronization state is not C, then a dead loop is performed. Continue execution (2).

Tryreadlock Flowchart:



5. Read and write lock in the lock source

public static class Readlock implements Lock, java.io.Serializable {
        private static final long Serialversionuid =-599 2448646407690164L;
        Private final sync sync;

        /**
         * Use implementation class to construct read
         lock
        /protected Readlock (Reentrantreadwritelock Lock) {
            sync = lock.sync;
        }

        /**
         * Acquire read lock
        /public void Lock () {
            sync.acquireshared (1);
        }

        /**
         * Only if the write lock is not persisted by another thread during the call, then acquire the read lock/public  boolean trylock () {return
            sync.tryreadlock ();
        }

		/**
         * Attempt to release read lock
         resource  /public void unlock () {
            sync.releaseshared (1);
        }
}

6. Write lock source code in read and write lock

public static class Writelock implements Lock, java.io.Serializable {
        private static final long Serialversionuid =-49 92448646407690164L;
        Private final sync sync;

        /**
         * Use implementation class to construct write
         lock
        /protected Writelock (Reentrantreadwritelock Lock) {
            sync = lock.sync;
        }

        /**
         * Get write lock
        /public void Lock () {
            sync.acquire (1);
        }

        /**
         * Gets the lock only when the write lock is not persisted by another thread during the call.
         */Public
        Boolean Trylock () {return
            sync.trywritelock ();
        }

        /**
         * Release Write lock */public
        void unlock () {
            sync.release (1);
        }
}

7. Reading Summary

(1) Reentrantreadwritelock read-write strategy: As long as the write thread is written, the other threads write and read are blocked. Read threads are read, other threads can read, but if other threads acquire a write lock, the updated data is not visible to other threads that read the lock outside of itself, so the lock cannot be upgraded.

(2) Reentrantreadwritelock Note: The current thread is already holding a write lock, the current thread can continue to acquire write locks, the process is called write-back. The current thread can also release the write lock, and then acquire the read lock, which is called a lock demotion, but other threads are not allowed to be read.

(3) Reentrantreadwritelock Read and write design: Read and write lock in two, high 16 bits for reading operations, low 16 bits for write operations.



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.