An introduction
In a multi-threaded environment, the same data read and write, will involve thread security issues. For example, when one thread reads the data, another thread writes the data, causing inconsistencies in the data before and after the thread writes the data, and the other thread is writing, as well as causing inconsistencies in the data that the thread sees before and after. This time can be added to the read-write method of the mutex , can only allow one thread of a read or write operation, and not allow other threads to read or write operations, so that the problem is resolved, but the efficiency is greatly compromised. Because in a real business scenario, a piece of data, the number of times to read data is usually higher than the operation of writing data, and the thread-to-thread read operation 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
Read and write locks: divided into reading and writing locks, multiple read locks are not mutually exclusive, read lock and write lock mutex, which is controlled by the JVM itself.
Reentrantreadwritelock is a reentrant read-write lock that allows multiple read threads to get Readlock, but only one write thread is allowed to get Writelock
Two preparation
mechanism for reading and writing locks:
"read-read" is not mutually exclusive"read-write" Mutex"Write-write" mutex
Reentrantreadwritelock does not support lock escalation (change from read lock to write lock)
New Reentrantreadwritelock (); Rtlock.readlock (). Lock (); System.out.println ("Get readlock.") ); Rtlock.writelock (). Lock (); System.out.println ("blocking");
Lock Escalation
This code will deadlock, do not release the read lock to apply for write lock
reentrantreadwritelock support for lock demotion (from write lock to read lock)
New Reentrantreadwritelock (); Rtlock.writelock (). Lock (); System.out.println ("Writelock"); Rtlock.readlock (). Lock (); System.out.println ("get read lock");
Lock Downgrade
The above code does not cause a deadlock, but does not have the correct release lock. Downgrading from a write lock to a read lock does not automatically release the write lock acquired by the current thread and still needs to be displayed for release, otherwise the thread will never get a write lock.
Examples of three Javadoc
1 classCacheddata {2 Object data;3 volatile BooleanCachevalid;4 FinalReentrantreadwritelock RWL =NewReentrantreadwritelock ();5 6 Public voidProcesscacheddata () {7 Rwl.readlock (). Lock ();8 if(!cachevalid) {9 //must release read lock before acquiring write lockTen rwl.readlock (). Unlock (); One Rwl.writelock (). Lock (); A Try { - //recheck state because another thread might have,acquired write lock and changed state before we did. - if(!cachevalid) { thedata = ... -Cachevalid =true; - } - //downgrade the write lock by acquiring a read lock before releasing the write lock (note that the write lock is not released at this time) + Rwl.readlock (). Lock (); -}finally { +Rwl.writelock (). Unlock ();//write lock is released and read lock is held at this time A } at } - - Try { - Use (data); -}finally { - rwl.readlock (). Unlock (); in } - } to}
Readwritelock Instances
Note that the final release of the write lock "line21", before is to read the lock "line19", because in the get process, there may be other threads competing to lock or update data, will produce dirty read.
Four-cache Example
Private StaticMap<integer, integer> cache =Maps.newhashmap (); PrivateReadwritelock Readwritelock =NewReentrantreadwritelock (); Publicinteger Get (integer key) {integer value; Readwritelock.readlock (). Lock (); Try{Value=Cache.get (key); if(Value = =NULL) {readwritelock.readlock (). Unlock (); Readwritelock.writelock (). Lock (); Try { if(Value = =NULL) {Value= 1;//read from database, etc.} readwritelock.readlock (). Lock (); } finally{readwritelock.writelock (). Unlock (); } } } finally{readwritelock.readlock (). Unlock (); } returnvalue; } Public voidput (integer key, integer value) {Readwritelock.writelock (). Lock (); Cache.put (key, value); Readwritelock.writelock (). Unlock (); }
Cache
"java.util.concurrent and contract" the Reentrantreadwritelock