In the case of high concurrency, when using the Ehcache cache, the data we read may be wrong due to concurrent reads and writes, and the data we write may be accidentally overwritten. Fortunately, Ehcache provided us with a read (read)/write (write) lock for the cache element key. The read lock on key can be held by multiple threads at the same time, but until those threads have freed the read lock, the other threads can get the write lock. And at the same time the write lock for this key can only be held by one thread.
When a thread obtains a write lock for a cache key:
1) This thread can take a read lock on the key (that is, the thread can read the value of the key);
2) Other threads cannot obtain the read and write locks of the key (that is, the value of the key cannot be read or written by other threads). Wait until the thread releases the write lock on the key before it can be obtained.
Example:
private static void Testwritelock () {Cache cache = Cachemanager.getcache ("Cache2");
String key = "Key1"; Thread t1 = new Thread (new Runnable () {@Override public void run () {try {Cache.acquirewritelockonkey (key)
;
for (int i = 0; i < 5; i++) {Cache.put (New Element (key, i));
System.out.println ("Thread1 put" + i + "to" + key);
Thread.Sleep (500);
}} catch (Exception e) {e.printstacktrace ();
} finally {Cache.releasewritelockonkey (key);
System.out.println ("Thread1 end.");
}
}
});
Thread t2 = new Thread (new Runnable () {Boolean canRead = false;
Boolean canWrite = false;
@Override public void Run () {try {//test one while (true) {Thread.Sleep (300);
if (Cache.trywritelockonkey (key, 1)) {System.out.println ("Thread2 get write Lock success.");
CanWrite = true;
} else {System.out.println ("Thread2 cannot get write lock."); } if (Cache.tryreadlockoNkey (key, 1)) {System.out.println ("Thread2 get read lock success.");
CanRead = true;
} else {System.out.println ("thread2 cannot get read lock.");
} if (CanRead && canWrite) {break;
}}//Test one//test two//Thread.Sleep (1000); for (int i = ten; I < i++) {//Cache.put (New Element (key, i));//System.out.println ("Thread2 put
"+ i +" to "+ key);
}//Test two//test three//Thread.Sleep (1000);
System.out.println ("Thread2 Get value of" + Key + ":" + cache.get (key). Getobjectvalue ());
Test three} catch (Exception e) {e.printstacktrace ();
} finally {System.out.println ("Thread2 end.");
}
}
});
T1.start ();
T2.start (); }
Thread 1 First runs first, it gets the write lock of the element "Key1", and then updates the Key1 value every 0.5 seconds. Run after thread 2.
In the test example, thread 2 will fail every 0.3 seconds to determine if the read and write locks of "Key1" can be obtained. Thread 2 can obtain the read and write locks for "Key1" after thread 1 ends and the write lock "Key1" is released.
The results of the operation are as follows:
Thread1 put 0 to Key1
thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread1 put 1 to Key1
thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread1 put 2 to Key1
thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread1 put 3 to Key1
thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread1 put 4 to Key1
Thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread2 cannot get write lock.
Thread2 cannot get read lock.
Thread1 end.
Thread2 Get write lock success.
Thread2 get read lock success.
Thread2 end.
In test example two, thread 2 attempts to update the value of the Key1 directly. However, because the write lock of Key1 is on the thread 1 hand at this time, it will be temporarily blocked (without error), and thread 2 will continue to run until thread 1 ends and release "Key1" write lock.
The results of the operation are as follows:
Thread1 put 0 to Key1
thread1 put 1 to Key1
Thread1 put 2 to Key1 Thread1
put 3 to Key1
Thread1 put 4 to K Ey1
thread1 end.
Thread2 put to Key1
Thread2 put one to Key1 Thread2 put from Key1 Thread2 put to Key1 thread2
put 14 To Key1
thread2 end.
In test example three, thread 2 attempts to read the value of the Key1. However, because the write lock of Key1 is on the thread 1 hand at this time, it will be temporarily blocked (without error), and thread 2 will continue to run until thread 1 ends and release "Key1" write lock.
The results of the operation are as follows:
Thread1 put 0 to Key1
thread1 put 1 to Key1
Thread1 put 2 to Key1 Thread1
put 3 to Key1 Thread1
put 4 To Key1
Thread1 end.
Thread2 get value of Key1:4
thread2 end.
when a thread obtains a read lock on a cache key:
1) This thread cannot get the write lock of the key (that is, the thread cannot write the value of the key);
2) Other threads can take the read lock on the key, but cannot get the write lock (that is, the value of the key can be read by other threads, but not written). The write lock cannot be obtained until the thread (or all threads) releases the read lock on the key.
Example:
private static void Testreadlock () {Cache cache = Cachemanager.getcache ("Cache2");
String key = "Key1";
Cache.put (The new Element (Key, "value"));
thread T1 = new Thread (new Runnable () {int i = 0;
@Override public void Run () {try {Cache.acquirereadlockonkey (key);
System.out.println ("Thread1 get read lock success.");
Test one while (true) {Thread.Sleep (500);
if (Cache.trywritelockonkey (key, 1)) {System.out.println ("Thread1 get write Lock success.");
Break
} else {System.out.println ("Thread1 cannot get write lock.");
i++;
if (i = = 5) {Cache.releasereadlockonkey (key);
}}}//Test one//test two//Cache.put (New Element (Key, "value1"));
System.out.println ("Thread1 put value1 to" + key + "success.");
Test two} catch (Exception e) {e.printstacktrace ();
} finally {Cache.releasewritelockonkey (key);
System.out.println ("Thread1 end."); }
}
});
T1.start (); }
In the test example, thread 1 acquires the "Key1" read lock and cannot continue to acquire the write lock until the read lock is released to obtain the write lock.
The results of the operation are as follows:
Thread1 get read lock success.
Thread1 cannot get write lock.
Thread1 cannot get write lock.
Thread1 cannot get write lock.
Thread1 cannot get write lock.
Thread1 cannot get write lock.
Thread1 release read lock.
Thread1 Get write lock success.
Thread1 end.
In test example two, thread 1 tries to update the value of "Key1". However, because thread 1 holds the read lock for "Key1" at this point, the method then goes into blocking and deadlock (because thread 1 does not release the read lock).
The results of the operation are as follows:
Thread1 get read lock success.
(No print "Thread1 end.")
The other thread can get the read lock, but cannot get the example of the write lock temporarily omitted:
Finally, note that the Acquirereadlockonkey () and Acquirewritelockonkey () methods do not give an error, up to the blocking state. However, for the Releasereadlockonkey () and Releasewritelockonkey () methods, if the thread holding the read or write lock is not the thread, or the thread has previously released a read or write lock, Then calling these two methods again will cause an error. The error message is as follows:
Java.lang.IllegalMonitorStateException:attempt to unlock read lock, not locked by current thread at
java.util.concur Rent.locks.reentrantreadwritelock$sync.unmatchedunlockexception (reentrantreadwritelock.java:444) at
Java.util.concurrent.locks.reentrantreadwritelock$sync.tryreleaseshared (reentrantreadwritelock.java:428)
At Java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared (abstractqueuedsynchronizer.java:1341) At
Java.util.concurrent.locks.reentrantreadwritelock$readlock.unlock (reentrantreadwritelock.java:881)
At Net.sf.ehcache.concurrent.ReadWriteLockSync.unlock (readwritelocksync.java:64) at
Net.sf.ehcache.Cache.releaseLockOnKey (cache.java:3953) at
Net.sf.ehcache.Cache.releaseReadLockOnKey ( cache.java:4008) at
Com.demo.cache.testcachemanager$1.run (testcachemanager.java:46)
at Java.lang.Thread.run (thread.java:745)
Exception in Thread "Thread-2" java.lang.IllegalMonitorStateException at
Java.util.concurrent.locks.reentrantreadwritelock$sync.tryrelease (reentrantreadwritelock.java:371) at
Java.util.concurrent.locks.AbstractQueuedSynchronizer.release (abstractqueuedsynchronizer.java:1261) at
Java.util.concurrent.locks.reentrantreadwritelock$writelock.unlock (reentrantreadwritelock.java:1131) at
Net.sf.ehcache.concurrent.ReadWriteLockSync.unlock (readwritelocksync.java:64) at
Net.sf.ehcache.Cache.releaseLockOnKey (cache.java:3953) at
Net.sf.ehcache.Cache.releaseWriteLockOnKey ( cache.java:4017) at
Com.demo.cache.testcachemanager$1.run (testcachemanager.java:48)
at Java.lang.Thread.run (thread.java:745)