Wiki
Clone wikiatlassian-util-concurrent / ManagedLock
A ManagedLock
is an encapsulation of a lock that means the locking (and correct unlocking) is handled for you. It is most helpful in cases where the locks may be managed for you (in a for instance an adaptive striped locking service).
Usage
ManagedLock lock = lockService.get(key);
return lock.withLock(new Supplier<String>() {
public String get() {
return "this is the " + counter.get() + "th call!";
}
});
There are also versions that will accept a Callable
(which therefore declares that it throws Exception
) and Runnable
(which therefore returns void
).
There is also the sub-interface ManagedLock.ReadWrite
for dealing with read/write locking.
ManagedLocks
This class has most of the factory methods you should need to create and manage instances of ManagedLock
. The simplest (creating one that wraps a ReentrantLock
) is:
ManagedLock lock = ManagedLocks.newManagedLock();
If you need to supply a Lock
that was created somewhere else, is a specialised implementation or is needed for tracking/monitoring:
ManagedLock lock = ManagedLocks.manage(myLock);{code}
Lock striping
You can also create factories that manage locks for you based on some input. These are useful for striping, and are optimised to keep as low a memory profile as possible by using weak references internally.
The factories are of the shape Function<T, ManagedLock>
where T is some value* we base our stripe on.
If say we want to stripe based on an entity's Long id, we might have a lock factory:
Function<Long, ManagedLock> lockFactory = ManagedLocks.weakManagedLockFactory();
…
// protect update per entity
return lockFactory.get(entity.id()).withLock(new Supplier<Entity>() {
public Entity get() {
return service.update(entity);
}
});
If a Lock is not used anymore then it becomes eligible for GC.
To restrict the maximum number of locks used, or to make the usage easier, you can pass in a Function that extracts the value from the input:
// simple extract function
Function<Entity, ManagedLock> lockFactory =
ManagedLocks.weakManagedLockFactory(
new Function<Entity, Long>() {
public Long get(Entity entity) {
return entity.id();
}
}
);
…
// keep the max locks to 16
Function<Entity, ManagedLock> lockFactory =
ManagedLocks.weakManagedLockFactory(
new Function<Entity, Integer>() {
public Integer get(Entity entity) {
return (int) (entity.id() % 16);
}
}
);
- By value we mean an immutable object that correctly implements the
hashcode/equals
contract.
src/main/java/com/atlassian/util/concurrent/ManagedLock.java src/main/java/com/atlassian/util/concurrent/ManagedLocks.java
Updated