Previously we used the synchronized keyword to solve the thread synchronization problem. Let's take a look at the thread Lock provided after Java 5.0.
The implementation class of the Lock interface provides more flexible and extensive object Lock operations than using the synchronized keyword, and implements object Lock in an object-oriented way.
@ Overridepublic void run () {while (true) {Lock lock = new ReentrantLock (); try {lock. lock (); Thread. sleep (new Random (). nextInt (3000); String data = readData (); System. out. print ("read data:" + data);} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock ();}}}
Read/write locks are divided into read/write locks. Multiple read/write locks are not mutually exclusive. The read/write locks and write locks are mutually exclusive. This is controlled by JVM.
Import java. util. random; import java. util. concurrent. locks. readWriteLock; import java. util. concurrent. locks. reentrantReadWriteLock; public class ReadWriteLockTest {static ReadWriteLock rwl = new ReentrantReadWriteLock (); private static String data = null; public static void main (String [] args) {Runnable runnable1 = new MyRunnable1 (); Runnable runnable2 = new MyRunnable2 (); for (int I = 0; I <3; I ++) {new Thread (runnable1 ). start (); new Thread (runnable2 ). start () ;}} static class MyRunnable1 implements Runnable {@ Overridepublic void run () {writeData ("" + new Random (). nextInt (100);} static class MyRunnable2 implements Runnable {@ Overridepublic void run () {readData () ;}} private static void writeData (String var) {rwl. writeLock (). lock (); try {System. out. println (Thread. currentThread (). getName () + "prepare to write"); Thread. sleep (new Random (). nextInt (3000); data = var; System. out. println (Thread. currentThread (). getName () + "written");} catch (InterruptedException e) {e. printStackTrace ();} finally {rwl. writeLock (). unlock () ;}} private static void readData () {rwl. readLock (). lock (); // use the read lock to lock try {System. out. println (Thread. currentThread (). getName () + "read Preparation"); Thread. sleep (new Random (). nextInt (3000); System. out. println (Thread. currentThread (). getName () + "read completed");} catch (InterruptedException e) {e. printStackTrace ();} finally {rwl. readLock (). unlock ();}}}
Friends who have used the Hibernate framework may know that there is a cache mechanism in the Hibernate query database. If a data exists in the memory, it can be read concurrently, if there is no data in the cache, You need to obtain data from the database through mutual exclusion.
Import java. util. HashMap; import java. util. Map; import java. util. concurrent. locks. ReentrantReadWriteLock; public class CacheDemo {private Map
Cache = new HashMap
(); Public static void main (String [] args) {} private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock ();/*** multiple concurrent reads, mutually Exclusive write * @ param key * @ return */public Object getData (String key) {rwl. readLock (). lock (); Object value = null; try {value = cache. get (key); if (value = null) {rwl. readLock (). unlock (); // release the read lock rwl. writeLock (). lock (); // Add the write lock try {if (value = null) {// place another thread to load data value = ""; // here we simulate the query from the database if (value = null) {// TODO throw an exception} finally {rwl. writeLock (). unlock ();} rwl. readLock (). lock (); // return the lock to the read thread} finally {rwl. readLock (). unlock () ;}return value ;}}
The process for obtaining data is as follows:
1. Get the read lock and read data
2. If there is data, it will be returned directly, and the read lock will be released for other threads to read.
3. If there is no data in the memory, write the data to the memory from the database, release the read lock, and add the write lock (in this way, Data Writing can be mutually exclusive)
4. Release the write lock after reading the memory and return the read-back lock (corresponding to the unlock)
5. If there are multiple threads at the same time when adding the write lock, only one thread can grab the lock. After the lock thread releases the write lock, other threads will grab the write lock, however, if the data has been written to the memory, you need to determine whether the memory data is null. If not, the write lock is directly released.