In global regions, the system locks entries and the region during updates. You can also explicitly lock the region and its entries as needed by your application. Locking includes system settings that help you optimize performance and locking behavior between your members.
In regions with global scope, locking helps ensure cache consistency.
Locking of regions and entries is done in two ways:
Explicit. You can use the API to explicitly lock the region and its entries. Do this to guarantee atomicity in tasks with multi-step distributed operations. The Region
methods org.apache.geode.cache.Region.getDistributedLock
and org.apache.geode.cache.Region.getRegionDistributedLock
return instances of java.util.concurrent.locks.Lock
for a region and a specified key.
Note: You must use the Region
API to lock regions and region entries. Do not use the DistributedLockService
in the org.apache.geode.distributed
package. That service is available only for locking in arbitrary distributed applications. It is not compatible with the Region
locking methods.
Getting a lock on a region or entry is a two-step process of getting a lock instance for the entity and then using the instance to set the lock. Once you have the lock, you hold it for your operations, then release it for someone else to use. You can set limits on the time spent waiting to get a lock and the time spent holding it. Both implicit and explicit locking operations are affected by the timeouts:
The lock timeout limits the wait to get a lock. The cache attribute lock-timeout
governs implicit lock requests. For explicit locking, specify the wait time through your calls to the instance of java.util.concurrent.locks.Lock
returned from the Region
API. You can wait a specific amount of time, return immediately either with or without the lock, or wait indefinitely.
<cache lock-timeout="60">
</cache>
gfsh:
gfsh>alter runtime --lock-timeout=60
The lock lease limits how long a lock can be held before it is automatically released. A timed lock allows the application to recover when a member fails to release an obtained lock within the lease time. For all locking, this timeout is set with the cache attribute lock-lease
.
<cache lock-lease="120"> </cache>
gfsh:
gfsh>alter runtime --lock-lease=120
For each global region, one of the members with the region defined will be assigned the job of lock grantor. The lock grantor runs the lock service that receives lock requests from system members, queues them as needed, and grants them in the order received.
The lock grantor is at a slight advantage over other members as it is the only one that does not have to send a message to request a lock. The grantor’s requests cost the least for the same reason. Thus, you can optimize locking in a region by assigning lock grantor status to the member that acquires the most locks. This may be the member that performs the most puts and thus requires the most implicit locks or this may be the member that performs many explicit locks.
The lock grantor is assigned as follows:
You can request lock grantor status:
At region creation through the is-lock-grantor
attribute. You can retrieve this attribute through the region method, getAttributes
, to see whether you requested to be lock grantor for the region. Note: The is-lock-grantor
attribute does not change after region creation.
After region creation through the region becomeLockGrantor
method. Changing lock grantors should be done with care, however, as doing so takes cycles from other operations. In particular, be careful to avoid creating a situation where you have members vying for lock grantor status.
These two examples show entry locking and unlocking. Note how the entry’s Lock
object is obtained and then its lock method invoked to actually set the lock. The example program stores the entry lock information in a hash table for future reference.
/* Lock a data entry */
HashMap lockedItemsMap = new HashMap();
...
String entryKey = ...
if (!lockedItemsMap.containsKey(entryKey))
{
Lock lock = this.currRegion.getDistributedLock(entryKey);
lock.lock();
lockedItemsMap.put(name, lock);
}
...
/* Unlock a data entry */
String entryKey = ...
if (lockedItemsMap.containsKey(entryKey))
{
Lock lock = (Lock) lockedItemsMap.remove(name);
lock.unlock();
}