Juc Source Analysis 13-locks-reentrantreadwritelock

Source: Internet
Author: User
Tags cas lock queue

Reentrantreadwritelock-based AQS implementation of read-write lock synchronization:

1. Using the shared mode to achieve read lock, exclusive mode to achieve write lock;

2. Support for fair and non-fair, non-fair situations where a read lock blocking write lock scenario may occur;

3. Write lock block write lock and read lock, read lock block write lock;

4. Write lock can be downgraded to read lock, read lock cannot be upgraded to write lock, only first release and then lock;

5. Write lock support condition condition;

6. Read/write locks support timeout/interrupt lock;

7. Suitable for reading and writing less scenes.


Implements the Readwritelock interface for returning read/write locks:

<span style= "FONT-SIZE:18PX;" >public interface Readwritelock {    /**     * Returns the lock used for reading.     *    /Lock readlock ();    /**     * Returns the lock used for writing.     *    /Lock writelock ();} </span>

Look at the AQS implementation of the Inner class:

<span style= "FONT-SIZE:18PX;" >abstract Static class Sync extends Abstractqueuedsynchronizer {private static final long Serialversionuid = 631767    1515068378041L;    The Int state field in/*aqs is split into 2 parts, the high 16 bits represent the number of times a shared read lock is held (the number of times each thread is re-entered, saved by Holdcounter), and the low 16 bits represent the number of times the exclusive write lock is re-entered/static final int Shared_shift = 16; Offset unit static final int shared_unit = (1 << shared_shift); 00000000 00000001 00000000 00000000 State is split into 2 parts, so the number of read lock hold counts will require this value to be compared to static final int max_count = (1 << SHA Red_shift)-1; 00000000 00000000 11111111 11111111 Maximum number of read/write locks held 65535,2 16-1 static final int exclusive_mask = (1 << shared_shi FT)-1; 00000000 00000000 11111111 11111111/** Read-lock high 16-bit unsigned offset 16-bit, equivalent to the number of hold holds held for a read lock */static int sharedcount (int c) {retur n C >>> Shared_shift; }/** returns the number of re-entry of the write lock, State2 case: If you have read the lock, it must be greater than 65535, the use of a high 16-bit, do & operation is equal to 0, you can use the State!=0 plus this return value!=0 judge has read the lock if it is a write lock, it is certainly less than 65535, Using a low 16 bit, do & operation returns the number of times the write lock is re-entered */static int exclusivecount (int c) {return C & exclusIve_mask;        }/** defines the class that holds the read lock per thread in the number of times */static final class Holdcounter {int count = 0;    Using the ID instead of the Thread to save, compile the garbage stuck final long tid = Thread.CurrentThread (). GetId (); }/** ThreadLocal subclass, holding holdcounter*/static final class Threadlocalholdcounter extends Threadlocallook at the fair and unfair strategy:

<span style= "FONT-SIZE:18PX;"    >static Final class Nonfairsync extends Sync {private static final long serialversionuid = -8159625535654395037l;        Final Boolean Writershouldblock () {return false;//non-fair write, can jump queue} final Boolean readershouldblock () {    /* is the check queue head of next is not exclusive node */return apparentlyfirstqueuedisexclusive ();    }}final Boolean apparentlyfirstqueuedisexclusive () {Node h, S;        Return (h = head)! = null && (s = h.next)! = null &&!s.isshared () && S.thread! = NULL;}     The fair is going to line up static final class Fairsync extends Sync {private static final long serialversionuid = -2274990926593161451l;    Final Boolean Writershouldblock () {return hasqueuedpredecessors ();    } Final Boolean Readershouldblock () {return hasqueuedpredecessors ();  }}aqs:public Final Boolean hasqueuedpredecessors () {//The correctness of this depends on head being initialized// Before tail andOn Head.next being accurate if the current//thread are first in queue. Node t = tail;    Read fields in reverse initialization order Node h = head;    Node s; return h! = T && ((s = h.next) = = NULL | | S.thread! = thread.currentthread ());} </span>

The read and write lock classes in the inner classes are also called Aqs, and there are some ways to support timeouts or interrupts, and some other monitoring classes are easy to read.

remember that the Aqs int state is split into 2 parts: The high 16 bits are the number of read lock holds (the re-entry of the thread is held by other variables), the low 16 bits are the number of write-lock re-entry, shared read, exclusive write, read lock block write lock, write lock block write lock and read lock, write lock can be read lock, read lock cannot be promoted to write lock . Finally summarize the acquire and release of read-write lock to determine the approximate process:

Write lock Acquire:

1. Gets the current thread, the state value, and the number of write lock re-entry times;
2. If the state is not 0, it indicates that the lock is occupied, the lock may be read lock, and the need to continue to judge;
3. In case the state is not 0, if the write lock is re-entered as 0, the read lock is occupied because the read lock blocks the write lock, and all returns false;
4. In case the state is not 0, if the write lock is not 0, the write lock is occupied because it can be re-entered, so it is determined whether it is the current thread, not false;
5. In 3, 4 judge no problem, that is, the current thread write lock re-entry, it is determined that the write lock after re-entry is greater than the maximum limit, such as reached, abnormal;
6. If the 5 judgment does not reach the maximum thread, then set the write lock re-entry number, return True, get success;
7. If the 2 judgment lock is not held, based on the queue policy to determine whether the write needs to block (non-normal, write does not need to block, fair to determine whether Head->next is null or not the current thread), need to block return false, hang, do not need to block the CAS operation to set the state value;
8. If 7 requires blocking or CAS setting fails, returns false, hangs;
9. If 7 does not need to block and CAs succeeds, the exclusive thread is set to return True,acquire successfully.

Write lock Release:

1. First determine whether the current thread is held, no exception;
2. Calculate the value after the state is released;
3. Determine if the write lock re-entry after release is 0;
4. If 3 is true, the write lock is re-entered as 0 then the exclusive thread is set to null;
5. Finally, the state value of AQS is set and the result of 3 is returned.


Read lock Acquire:

1. Get current thread and state lock hold times
2. A thread holds a write lock that can be downgraded to a read lock to determine if there are any other threads holding a write lock, if any, because the write lock blocks the read lock, then hangs the current thread;
3. If 2 No other thread holds a write lock, indicating that the write lock is not occupied, to improper front-line holding, then continue to obtain read lock hold;
4. Determine the 3 conditions:
4.1) Read release does not need to suspend, the non-normal judge whether there is head->next as a read thread, fair to determine whether the head->next null or non-current thread;
4.2) read lock holding is less than maximum;
4.3) CAs Set read lock held successfully
5. If 4 of the judgment is not a problem, continue to determine whether read lock holding is 0:
5.1) 0 for the first time hold read lock, set 2 first variable cache first hold the read thread and first hold the read thread of the number of times, so processing, if only one read, then do not have to query the cache;
5.2) If the read lock is not 0, the thread holds the read lock to determine if the current threads are the first to hold the read thread before the cache, and if so, the number of times the first hold read thread of the cache is accumulated;
5.3) If none of the above 2 are satisfied, then take the current thread's hold from the cache's holding variable, and then increase the number of times to acquire success
6. If the condition of 4 is not satisfied, then for loop processing the current thread, the process is roughly the same as 2, 3, 4, 5:
6.1) First determine if there is a write lock, if you have to continue to determine whether other threads hold, if other threads hold, then hang;
6.2) If no thread holds a write lock, determine if the read is blocking, and if it needs to block, continue to judge:
6.2.1) has acquired the re-entry of the read lock, even if it needs to be blocked, go to 6.3 processing, acquire success;
6.2.1) If it is the first request of the other thread, plus the above to determine the need to block, then acquire failure, blocking;
6.3) above to judge acquire no problem, judge whether the holding of reading to reach the maximum, the largest that is abnormal, not under the processing of some cache variables, with 5 of the processing, acquire success.

Read Lock release:

1. Take the current thread;
2. Determine if a read lock has been held:
1) If yes, determine the number of re-entry, 1 for the direct read lock is NULL, otherwise decrements the number of re-entry;
2) If not, then take the current thread's re-entry from the hold of the cache, if the re-entry is less than or equal to 1, need to remove the current thread from the holding cache, there is a judgment less than or equal to 0, do not understand what scene appears, and finally decrement;
The 3.for loop sets the number of read locks held and returns the comparison value of holding times to 0.


Finally read the Aqs part, life is not dead, study more than!







Reference:

http://ifeve.com/juc-reentrantreadwritelock/#more-9724

http://brokendreams.iteye.com/blog/2250866

Juc Source Analysis 13-locks-reentrantreadwritelock

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.