blob: 313a19b2dfe583aacf8e2e6a38e3183e2015dd59 [file] [log] [blame]
---
title: Locking in Global Regions
---
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
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.
<a id="locking_in_global_regions__section_065B3A57CCCA4F17821D170A312B6675"></a>
In regions with global scope, locking helps ensure cache consistency.
Locking of regions and entries is done in two ways:
1. **Implicit**. <%=vars.product_name%> automatically locks global regions and their data entries during most operations. Region invalidation and destruction do not acquire locks.
2. **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.
## <a id="locking_in_global_regions__section_5B47F9C5C27A4B789A3498AC553BB1FB" class="no-quick-link"></a>Lock Timeouts
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.
``` pre
<cache lock-timeout="60">
</cache>
```
gfsh:
``` pre
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`.
``` pre
<cache lock-lease="120"> </cache>
```
gfsh:
``` pre
gfsh>alter runtime --lock-lease=120
```
## <a id="locking_in_global_regions__section_031727F04D114B42944872360A386907" class="no-quick-link"></a>Optimize Locking Performance
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 grantors 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:
- Any member with the region defined that requests lock grantor status is assigned it. Thus at any time, the most recent member to make the request is the lock grantor.
- If no member requests lock grantor status for a region, or if the current lock grantor goes away, the system assigns a lock grantor from the members that have the region defined in their caches.
You can request lock grantor status:
1. 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.
2. 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.
## <a id="locking_in_global_regions__section_34661E38DFF9420B89C1A2B25F232D53" class="no-quick-link"></a>Examples
These two examples show entry locking and unlocking. Note how the entrys `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.
``` pre
/* 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);
}
...
```
``` pre
/* Unlock a data entry */
String entryKey = ...
if (lockedItemsMap.containsKey(entryKey))
{
Lock lock = (Lock) lockedItemsMap.remove(name);
lock.unlock();
}
```