Basic Introduction:
Read and write Lock: Readwritelock
In a multi-threaded environment, reading and writing to the same data will involve thread-safety issues. For example, when one thread reads the data, another thread writes the data, which results in inconsistency of the data before and after; one thread writes the data and another thread writes it, which also causes inconsistencies in the data that is seen before and after the thread.
In this case, you can add a mutex in the read-write method, you can only allow one thread of a read or write operation, and not allow other threads read or write operations, this is to solve the above problems, but the efficiency is greatly compromised. Because in a real business scenario, a piece of data, the number of operations to read data is usually higher than the operation of the data, and thread and thread reading is not related to thread safety issues, there is no need to join the mutex, as long as the read-write, write-write during the lock on the line.
In this case, read-write locks are the best solution.
2 internal classes are defined in the Reentrantreadwritelock. Reentrantreadwritelock.readlock and Reentrantreadwritelock.writelock, respectively, are used to represent read locks and write locks, and Reentrantreadwritelock objects provide Readlock () and Writelock () method for fetching read and write locks
Where: Read locks allow multiple reader threads to hold simultaneously, while write locks can be held at most one writer thread. The use of read and write locks is: The frequency of reading data is much greater than the frequency of modifying shared data. Using read-write locks to control access to shared resources in these situations can improve concurrency performance. If a thread already holds a write lock, it can hold a read-write lock again. Conversely, if a thread already holds a read lock, the write lock cannot be held until the read lock is freed. The Newcondition () method that can call the write lock gets the condition object that is bound to the write lock, which is no different from the normal mutex, but the newcondition () method that invokes the read lock throws an exception.
Two mutually exclusive locking mechanisms:
1, synchronized
2, Reentrantlock
Reentrantlock is a new feature of Jdk5, Reentrantlock can completely replace the replacement of synchronized traditional locking mechanism, and the use of Reentrantlock is more object-oriented, but also more flexible
Read and write lock mechanism:
"Read-read" is not mutually exclusive
"Read-write" mutex
"Write-write" mutex
That is to be ensured at all times:
Only one thread is writing;
The write operation waits while the thread is reading;
While the thread is writing, the write operations and read operations of the other threads wait;
Lock demotion: Change from write lock to read lock; Lock escalation: From read lock to write lock. Read locks can be shared by multiple threads, and write locks are single-threaded exclusive. This means that the concurrency limit for write locks is higher than read locks
The following code produces a deadlock, because the same thread, in the absence of the release of the read lock, to apply for the write lock, which belongs to the lock escalation, Reentrantreadwritelock is not supported.
Readwritelock Rtlock = new Reentrantreadwritelock ();
Rtlock.readlock (). Lock ();
System.out.println ("Get readlock.");
Rtlock.writelock (). Lock ();
System.out.println ("Blocking");</span></span>
Reentrantreadwritelock support for lock demotion, the following code does not produce a deadlock.
Readwritelock Rtlock = new Reentrantreadwritelock ();
Rtlock.writelock (). Lock ();
System.out.println ("Writelock");
Rtlock.readlock (). Lock ();
SYSTEM.OUT.PRINTLN ("Get read lock");
This code does not cause a deadlock, but does not release the lock correctly. Demoting A read lock from a write lock does not automatically release the write lock acquired by the current thread and still needs to be displayed, otherwise the other thread will never get the write lock. The release and acquisition of a lock can be seen under: The acquisition and release of a reentrant lock something to be aware of
<span style= "White-space:pre" > </span>final readwritelock readwritelock = new Reentrantreadwritelock ();
Thread wt = new thread (new Runnable () {public
void run () {
readwritelock.writelock (). Lock ();
System.out.println ("Writelock");
Readwritelock.readlock (). Lock ();
System.out.println ("Readlock");
Readwritelock.readlock (). Unlock ();
System.out.println ("block");
}
);
Wt.start ();
try {
Thread.Sleep (MB);
} catch (Interruptedexception e) {
//TODO auto-generated catch
block E.printstacktrace ();
}
System.out.println ("main blocking.");
Readwritelock.readlock (). Lock ();</span>
Application Scenario:
Read and write lock applicable scene
Read more and write less high concurrency environment, it can be said that this scenario is the most suitable for use Readwritelock.
Simple Mode code:
Import Java.util.concurrent.locks.ReadWriteLock;
Import Java.util.concurrent.locks.ReentrantReadWriteLock;
public class Singleton {private static Singleton instance = NULL;
private static Readwritelock rwl = new Reentrantreadwritelock (); Private Singleton () {}/** * The current thread acquires a read lock in the process of acquiring a write lock, which is called the Lock's reentrant, and then causes a write-lock demotion, known as a downgrade lock. From 3 to get write lock to 5 to read lock demote use reentrant to demote write locks, but allow the reader to use them only if all write locks held by the current thread have been released. 6 So in the process of reentry, other threads will not have access to the lock (the benefit). Just think, release the write lock, read the lock on the top, what's the disadvantage of doing so.
(if 5 and 6 are reversed) if you do this, you may be interrupted by other threads before you can get a read lock after releasing the write lock.
Steps to ———— > demote a Lock: First get write lock 3, then get read lock 5, finally release write lock 6 (emphasis) * @return/public static Singleton getinstance () { Rwl.readlock (). Lock (); 1 try {if (null = = instance) {Rwl.readlock (). Unlo CK (); 2 Rwl.writelock (). Lock (); 3 if (null = = instance)//4 {
Instance = new Singleton (); } rwl.readlock (). Lock (); 5 Rwl.writelock (). Unlock (); 6}} finally {Rwl.readlock (). Unlock ();
7} return instance; }
}
Code Analysis:
When n multithreading uses the same singleton instance object to invoke the GetInstance method, a thread concurrency problem is generated.
@1 line, the thread that runs to the @1 line waits for the write to complete when the wire is writing to the data, because the first thread that runs to the @3 is locked, then the data is required, and no thread is allowed to read or write.
When finished, a read-lock operation is added to the thread to prevent the other thread from writing the data again when it writes. After the first thread that runs to @3, a lot of threads,
may have been running to the @2, when the data modified, the release of the write lock, the other thread will be executed to @3, when the first thread has been modified by the data, so have a @4 judgment.
When you're writing a multithreaded program, to be placed in the context of concurrent threads, the ingenious use of reentrantreadwritelock, in use, attention to the lock of the downgrade, write lock can be read lock, read lock can not get write lock, so write a lock, you must first read lock to lift, Then read the lock.
Several aspects of attention during use:
Read lock is write lock operation, read lock does not row read lock operation, multiple read locks can be concurrent without blocking. That is, the write lock cannot be obtained by any thread until the read lock is fetched and the read lock is released.
When multiple read locks are in effect, the thread attempting to acquire the write lock is in a waiting state, and the thread attempting to acquire the write lock has the opportunity to acquire the write lock after the last read lock is released.
Write locks are write-lock, row-read-lock operation. When a thread acquires a write lock, other threads that attempt to acquire a write lock and attempt to acquire a read lock are in the waiting state until the write lock is freed.
Write locks are available for read locks, namely:
Rwl.writelock (). Lock ();
In the write lock state, you can get the read lock
Rwl.readlock (). Lock ();
Rwl.writelock (). Unlock ();
Read lock is not able to get write lock, if you want to write a lock, this thread must release the read lock held, that is:
Rwl.readlock (). Lock ();
//......
You must release the read lock before you can write the lock.
Rwl.readlock (). Unlock ();
Rwl.writelock (). Lock ();
When the current thread acquires a write lock, it acquires the read lock, which is called the Lock's reentrant, and then causes the write-lock to degrade, known as a degraded lock.
Get write lock from 3 to 5 into read lock demotion
With reentrant, write locks can be demoted, but only after all write locks held by the current thread have been freed are the reader allowed to use them again. 6
So in the process of reentry, other threads will not have access to the lock (the benefit). Just think, release the write lock, read the lock on the top, what's the disadvantage of doing so. (if 5 and 6 are reversed)
If you do this, you may be interrupted by other threads before you can get a read lock after releasing the write lock.
Steps to ———— > demote a lock: Get write lock 3 First, then get read lock 5, finally release write lock 6 (emphasis)