I. definition of Popular science
The two protagonists of this post are "synchronized" and "Read and write locks"
1) Synchronized
This synchronization keyword believes that we all use more, in the previous "How to share data between multiple threads" also detailed his application, in this is not much to say only do a few summary: Java provides this keyword, to prevent resource conflicts provided by built-in support. When a task executes to a synchronized-protected code fragment, it checks to see if the lock is available, then acquires the lock, executes the code, and releases the lock. This keyword can be used to decorate member methods and blocks of code
2 Read-write lock
We do nothing more than two things: "read" and "write", imagine a scenario where 10 threads should not be synchronized when reading a data at the same time. The answer is not necessary. There are only two situations that need to be synchronized: These 10 threads have both read and write to this common data the 10 threads write operations on public data above two point is that there is a need to synchronize the operation of data changes
So JAVA5 provides read-write lock which supports multithreading read operation, multithreading, mutual exclusion, and multithreading writing and writing mutually exclusive. Read operation is not mutually exclusive this helps improve performance, this is not before JAVA5two. Use a face test to compare these two points topic:"Whiteboard programming, Implementing a caching system"Topic Analysis:The understanding of this caching system: between the user and the database in the middle of a link, we know that users direct access to the database is much more than direct access to memory, so there is a buffer after the user access to the data, so that users first access to the buffer cache when the user needs data directly away, when there is no such data buffer, Access the database and place the data in the cache, so that the next user who needs this data accesses the memory directly.Core Code implementation:First implement Java code public synchronized object GetData (String key) {Object result = Map.get (key) with synchronized; if (result ==null) {result = "new";////replace access to database with data} return result; }
Public synchronized Object GetData (String key) {
object result = Map.get (key);
if (result ==null) {result
= "new";////replace access to database with data
} return result
;
}
Read-write lock implementation Java code PUBLIC OBJECT GETDATA (string key) { rw.readlock (). Lock ()//Read the locks before reading Object result = null; try{ result = map.get (key); //this if is the key, it avoids redundant several times to the data cry reads if (result==null) { //If you don't have the data you want in memory rw.readlock (). Unlock (); rw.writelock () . Lock (); if (result==null) { try{ // We use this instead of the steps to get data from database access result = "New"; }finally{ rw.writelock () Unlock (); } rw.readlock ()-Lock (); } } }finally{ rw.readlock () Unlock (); } return result; }
The public Object getData (String key) {
rw.readlock (). Lock ();//read lock
Object result = null before reading;
try{result
= Map.get (key);
This if is more critical, it avoids the extra number of times to cry the read if
(result==null) {
//If there is no data in memory
rw.readlock (). Unlock ();
Rw.writelock (). Lock ();
if (result==null) {
try{
//We use this in place of the steps to get data from the database access result
= "new";
} finally{
rw.writelock (). Unlock ();
}
Rw.readlock (). Lock ();}}
finally{
rw.readlock (). Unlock ();
}
return result;
}
Code Analysis: The first method of processing, the whole process is relatively thick, the code is relatively simple to perform a very low efficiency. The central idea of this approach is that no matter what you do, you are synchronized with all the public resources involved. This can be done but it's not good. The second type of read-write lock processing is obviously an optimization of the former, the second method does the following: With regard to the unlock operation, we know that as long as the lock has to be unlocked, but there is a situation when you are on the lock after performing the unlock operation of the program exception, then this may always exist. So for this problem we generally put the unlock operation in finally code block, we can guarantee that the lock will be solved. The above two if judgment, the first if I believe that everyone is very well understood. But why use the second if? Assuming a scenario where 10 threads are now reading this data, and the data does not exist with the buffer, then the first thread in the 10 threads will execute "rw.writelock (). Lock ();" The other nine threads will be blocked, and when the first thread is read, the buffer actually has this data, but the other nine blocks in the "Rw.writelock (). Lock ();" If you do not add this layer if they will continue to access the database, it can be seen that adding this layer of if to the entire process impact. This is a little bit more detail, and for this point the Java API documentation also takes into account that its sample code is as follows:
Java code class cacheddata { Object data; volatile boolean cachevalid; reentrantreadwritelock rwl = new reentrantreadwritelock (); void processcacheddata () { rwl.readlock (). Lock (); <span style= " Color: rgb (255, 0, 0); " >if (!cachevalid) </span> { // must release read lock before acquiring write lock rwl.readlock () Unlock (); Rwl.writelock ()-Lock (); // Recheck state because another thread might have acquired &NBSp; // write lock and changed state before we did. <span style= "COLOR: rgb (255, 0, 0); " > if (!cachevalid) </span> { data = ... cachevalid = true; } // downgrade by acquiring read lock before releasing write lock rwl.readlock (). Lock (); rwl.writelock (). Unlock (); // unlock write, still hold read } &Nbsp;use (data); rwl.readlock () unlock (); } }
Class Cacheddata {
Object data;
Volatile Boolean cachevalid;
Reentrantreadwritelock rwl = new Reentrantreadwritelock ();
void Processcacheddata () {
rwl.readlock (). Lock ();
if (!cachevalid) {
//must release read lock before acquiring write lock
rwl.readlock (). Unlock ();
Rwl.writelock (). Lock ();
Recheck state because another thread might have acquired
/ write lock and changed the state before we did.
if (!cachevalid) {
data = ...
Cachevalid = true;
}
Downgrade by acquiring read lock before releasing write lock
Rwl.readlock (). Lock ();
Rwl.writelock (). Unlock (); Unlock write, still hold read
} use
(data);
Rwl.readlock (). Unlock ();
}
Learning is continuing ... Go! Go! Go!!!