Ehcache (08)--the cache-blockingcache that can be blocked

Source: Internet
Author: User
Tags time in milliseconds

The Cache-blockingcache can be blocked

In the previous section we mentioned the issue of displaying the use of Ehcache locks, in fact we can also implicitly use the Ehcache lock, that is, through the Blockingcache. Blockingcache is a wrapper class for Ehcache that allows us to perform concurrent operations on Ehcache. Its internal locking mechanism is the same implementation as the display lock invocation, while the Net.sf.ehcache.concurrent.ReadWriteLockSync is used internally by the Java Readwritelocksync Java.util.concurrent.loc Ks. Readwritelock.

Blockingcache has two constructors, all of which receive a Ehcache object, one of which also receives a parameter numberofstripes that specifies the number of concurrent quantities, and the other does not have a numberofstripes parameter, but it uses the default value. The default value is 2048. The value of the numberofstripes must be greater than 0, and the exponent is 2. The received parameter, cache, represents the Ehcache object that is actually operating, and Blockingcache only encapsulates it to support concurrent operations.

Java code
  1. Public Blockingcache (final Ehcache cache, int numberofstripes) throws cacheexception {
  2. Super (cache);
  3. this. Stripes = numberofstripes;
  4. this. cachelockproviderreference = new atomicreference<cachelockprovider> ();
  5. }
  6. Public Blockingcache (final Ehcache cache) throws cacheexception {
  7. This (Cache, stripedreadwritelocksync.default_number_of_mutexes);
  8. }

Although our Ehcache is supported by lock invocation, the difference between Blockingcache and the display lock invocation is that it does not take the lock and release the lock directly through the Ehcache it holds, but is done internally by it. When a get element from Blockingcache is supported for concurrent reads, there is no problem, but if the corresponding key corresponding element does not exist, then the thread will be blocked until the corresponding put () method is called to hold the element of the corresponding key. How did this happen? Let's take a look at the source code of Blockingcache.

Java code
  1. Public Element get (final Object key) throws RuntimeException, locktimeoutexception {
  2. Getobserver.begin ();
  3. Sync lock = Getlockforkey (key);
  4. Acquiredlockforkey (Key, lock, Locktype.read);
  5. element element;
  6. Try {
  7. element = Underlyingcache.get (key);
  8. } finally {
  9. Lock.unlock (Locktype.read);
  10. }
  11. if (element = = null) {
  12. Acquiredlockforkey (Key, lock, Locktype.write);
  13. element = Underlyingcache.get (key);
  14. if (element! = null) {
  15. Lock.unlock (Locktype.write);
  16. Getobserver.end (Getoutcome.hit);
  17. } Else {
  18. Getobserver.end (getoutcome.miss_and_locked);
  19. }
  20. return element;
  21. } Else {
  22. Getobserver.end (Getoutcome.hit);
  23. return element;
  24. }
  25. }

The above is the core get () method of Blockingcache. We can see that first we get the corresponding key of the Sync,sync is an interface, its implementation class through the hold of the Lock object can be the corresponding key to the read lock or write lock. Another thing to note is that for the same key, we are using the same lock object. We know that there is no blocking between read lock, as described in the previous section for Ehcache display lock. So when we try to get an element:

1, if the corresponding key does not have write lock, then our code can be executed smoothly to determine whether element is null that line, this time to obtain the read lock has been released, will not affect the subsequent acquisition of its write lock;

2, if the corresponding key exists write lock, then call "Acquiredlockforkey" (Key, Lock, LockType. READ); " will be blocked until the corresponding write lock is released.

3. If the element obtained is not NULL, it will be returned directly.

4. If element is null, the write lock of the corresponding key is obtained, and if there is another thread that acquires the read lock for that key, it will block until there is no corresponding read lock.

5. Gets the corresponding element after the write lock is fetched again, since it is possible to get a corresponding write lock before the element is determined to be null, and the thread has put an appropriate element into the cache. If the corresponding element is obtained, the corresponding write lock is released, and then the retrieved element is returned.

6. Any thread that attempts to acquire a read or write lock on the corresponding key after acquiring the write lock will be blocked. If the corresponding element or null after the write lock is obtained, it will be returned directly. At this point the thread that calls the Get () method other than that thread will be blocked because the write lock for the current thread is not released.

Through the code and analysis above, we know that if the corresponding element does not exist when an element is obtained using the Get () method of Blockingcache, the thread will be blocked except for the thread that eventually acquires the write lock. And the thread that gets the write lock of the corresponding key how to release its write lock? This is released by put a corresponding key element in the Blockingcache. Blockingcache is implemented Ehcache interface, so Ehcache has the put* () method, Blockingcache have, but in Blockingcache's put* () A doandreleasewritelock logic is added to the method. Let's first look at the implementation of a put () method.

Java code
  1. Public void put (final element Element) {
  2. Doandreleasewritelock (new putaction<void> (element) {
  3. @Override
  4. Public Void put () {
  5. if (Element.getobjectvalue ()! = null) {
  6. Underlyingcache.put (Element);
  7. } Else {
  8. Underlyingcache.remove (Element.getobjectkey ());
  9. }
  10. Returnnull;
  11. }
  12. });
  13. }

We can see that a doandreleasewritelock () method is called inside the Put () method, which we can see from the method name and the parameters it receives, Doandreleasewritelock () The function of the Putaction method is to execute the put () method of the received parameter, then release the write lock of the corresponding key, and the Putaction construct is to receive an element parameter, so that the put () in the Putaction method, we can use the element object. The implementation of the Doandreleasewritelock () method is as follows.

Java code
  1. private <V> V doandreleasewritelock (putaction<v> putaction) {
  2. if (putaction.element = = null) {
  3. Returnnull;
  4. }
  5. Object key = PutAction.element.getObjectKey ();
  6. Sync lock = Getlockforkey (key);
  7. if (!lock.isheldbycurrentthread (Locktype.write)) {
  8. Lock.lock (Locktype.write);
  9. }
  10. Try {
  11. return putaction.put ();
  12. } finally {
  13. //release the writelock here. This'll has been acquired in the get, where the element is null
  14. Lock.unlock (Locktype.write);
  15. }
  16. }

From the source code we can see that its internal implementation is similar to what we envision. If the element held by Putaction is not NULL, it will determine if the current thread holds the write lock of the corresponding key, and if there is no write lock for the key, it will attempt to obtain its write lock. This time if the key's write lock has been fetched by another thread, it will be blocked here. Once you have the write lock, you can execute the put () method of the Putaction object, and you can release the write lock for the corresponding key when you have finished executing it.

Looking back, the previous get element from Blockingcache, if the corresponding element does not exist, then the thread will get to the corresponding key write lock (in the case of concurrency, which thread will get to the key of the write lock is indeterminate), Other threads that attempt to acquire the write or read locks of the key are blocked. If the thread puts a key element in the Blockingcache at this point, the write lock held by the thread is freed, and the other thread can obtain the read and write locks of the key, which makes it possible to call Blockingcache's get successfully ( ) method to get the corresponding element. Blockingcache is designed to use page caching, when multiple threads request a page at the same time, if there is a corresponding page in the cache, you can return directly, the read lock is not blocked between, if the corresponding page does not exist, then only one thread will return NULL, Other threads will be blocked, and when the return value is NULL, Ehcache will put the corresponding page into Blockingcache, at which point the write lock held by the thread will be freed, and the other blocked threads will be able to get to the page successfully. This avoids the need for multiple threads to put the corresponding page in the cache while the get-to element is null, resulting in unnecessary resource wastage. It would be appropriate to use Blockingcache if there is a need for page caching. More information about Ehcache using page caching will be introduced in the next Article blog post.

The Blockingcache just mentioned is designed for page caching. If the user needs to use Blockingcache himself, notice that the corresponding write lock is released when the obtained element is null. At this time there are two methods, one is to call Blockingcache's arbitrary put method, to store a corresponding key element, the second is to define a class to inherit the Blockingcache, and then open a method of releasing the lock, The corresponding logic can refer to the Blockingcache Doandreleaselock () method, because the access type of the method Getlockforkey () that acquires the lock internally is protected.

In addition, if the Blockingcache is blocked when acquiring a lock, the blocking time is variable and it can be very long. If you do not want the blocking time to be too long, we can set the maximum blocking time in milliseconds by Blockingcache's Settimeoutmillis () method, This throws locktimeoutexception if a thread has not acquired the corresponding lock within the timeoutmillis time.

(Note: This article is written based on Ehcache2.8.1)

Ehcache (08)--the cache-blockingcache that can be blocked

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.