public class DistributedLock extends Resource<DistributedLock>
The distributed lock resource provides a mechanism for nodes to synchronize access to cluster-wide shared resources.
This interface is an asynchronous version of Java's Lock.
atomix.getLock("my-lock").thenAccept(lock -> {
lock.lock().thenRun(() -> {
...
lock.unlock();
});
});
Locks are implemented as a simple replicated queue that tracks which client currently holds a lock. When a lock
is locked, if the lock is available then the requesting resource instance will immediately receive
the lock, otherwise the lock request will be queued. When a lock is unlocked, the next lock requester
will be granted the lock.
Distributed locks require no polling from the client. Locks are granted via session events published by the Atomix cluster to the lock instance. In the event that a lock's client becomes disconnected from the cluster, its session will expire after the configured cluster session timeout and the lock will be automatically released.
State of the lock. If the resource transitions to the
Resource.State#SUSPENDED state, that indicates that the underlying client is unable to communicate with the
cluster and another process may have been granted the lock. Lock holders should monitor the resource for state changes
and release the lock if the resource becomes suspended.
DistributedLock lock = atomix.getLock("my-lock").get();
lock.lock().thenRun(() -> {}
lock.onStateChange(state -> {
if (state == DistributedLock.State.SUSPENDED) {
lock.unlock();
System.out.println("lost the lock");
}
});
// Do stuff
);
Resource.Config, Resource.Options, Resource.State| Constructor and Description |
|---|
DistributedLock(CopycatClient client,
Resource.Options options) |
| Modifier and Type | Method and Description |
|---|---|
static Resource.Config |
config()
Returns a new lock configuration.
|
CompletableFuture<Long> |
lock()
Acquires the lock.
|
CompletableFuture<DistributedLock> |
open() |
static Resource.Options |
options()
Returns new lock options.
|
CompletableFuture<Long> |
tryLock()
Attempts to acquire the lock if available.
|
CompletableFuture<Long> |
tryLock(Duration timeout)
Attempts to acquire the lock if available within the given timeout.
|
CompletableFuture<Void> |
unlock()
Releases the lock.
|
public DistributedLock(CopycatClient client, Resource.Options options)
public static Resource.Options options()
public static Resource.Config config()
public CompletableFuture<DistributedLock> open()
open in interface Managed<DistributedLock>open in class Resource<DistributedLock>public CompletableFuture<Long> lock()
When the lock is acquired, this lock instance will publish a lock request to the cluster and await
an event granting the lock to this instance. The returned CompletableFuture will not be completed
until the lock has been acquired.
Once the lock is granted, the returned future will be completed with a positive Long value. This value
is guaranteed to be unique across all clients and monotonically increasing. Thus, the value can be used as a
fencing token for further concurrency control.
This method returns a CompletableFuture which can be used to block until the operation completes
or to be notified in a separate thread once the operation completes. To block until the operation completes,
use the CompletableFuture.join() method to block the calling thread:
lock.lock().join();
Alternatively, to execute the operation asynchronous and be notified once the lock is acquired in a different
thread, use one of the many completable future callbacks:
lock.lock().thenRun(() -> System.out.println("Lock acquired!"));
public CompletableFuture<Long> tryLock()
When the lock is acquired, this lock instance will publish an immediate lock request to the cluster. If the
lock is available, the lock will be granted and the returned CompletableFuture will be completed
successfully. If the lock is not immediately available, the CompletableFuture will be completed
with a null value.
If the lock is granted, the returned future will be completed with a positive Long value. This value
is guaranteed to be unique across all clients and monotonically increasing. Thus, the value can be used as a
fencing token for further concurrency control.
This method returns a CompletableFuture which can be used to block until the operation completes
or to be notified in a separate thread once the operation completes. To block until the operation completes,
use the CompletableFuture.get() method to block the calling thread:
if (lock.tryLock().get()) {
System.out.println("Lock acquired!");
} else {
System.out.println("Lock failed!");
}
Alternatively, to execute the operation asynchronous and be notified once the lock is acquired in a different
thread, use one of the many completable future callbacks:
lock.tryLock().thenAccept(locked -> {
if (locked) {
System.out.println("Lock acquired!");
} else {
System.out.println("Lock failed!");
}
});
public CompletableFuture<Long> tryLock(Duration timeout)
When the lock is acquired, this lock instance will publish an immediate lock request to the cluster. If the
lock is available, the lock will be granted and the returned CompletableFuture will be completed
successfully. If the lock is not immediately available, the lock request will be queued until the lock comes
available. If the lock timeout expires, the lock request will be cancelled and the returned
CompletableFuture will be completed successfully with a null result.
If the lock is granted, the returned future will be completed with a positive Long value. This value
is guaranteed to be unique across all clients and monotonically increasing. Thus, the value can be used as a
fencing token for further concurrency control.
Timeouts and wall-clock time
The provided timeout may not ultimately be representative of the actual timeout in the cluster. Because
of clock skew and determinism requirements, the actual timeout may be arbitrarily greater, but not less, than
the provided timeout. However, time will always progress monotonically. That is, time will never go
in reverse. A timeout of 10 seconds will always be greater than a timeout of 9 seconds, but the
times simply may not match actual wall-clock time.
This method returns a CompletableFuture which can be used to block until the operation completes
or to be notified in a separate thread once the operation completes. To block until the operation completes,
use the CompletableFuture.get() method to block the calling thread:
if (lock.tryLock(Duration.ofSeconds(10)).get()) {
System.out.println("Lock acquired!");
} else {
System.out.println("Lock failed!");
}
Alternatively, to execute the operation asynchronous and be notified once the lock is acquired in a different
thread, use one of the many completable future callbacks:
lock.tryLock(Duration.ofSeconds(10)).thenAccept(locked -> {
if (locked) {
System.out.println("Lock acquired!");
} else {
System.out.println("Lock failed!");
}
});
timeout - The duration within which to acquire the lock.public CompletableFuture<Void> unlock()
When the lock is released, the lock instance will publish an unlock request to the cluster. Once the lock has
been released, if any other instances of this resource are waiting for a lock on this or another node, the lock
will be acquired by the waiting instance before this unlock operation is completed. Once the lock has been released
and granted to any waiters, the returned CompletableFuture will be completed.
This method returns a CompletableFuture which can be used to block until the operation completes
or to be notified in a separate thread once the operation completes. To block until the operation completes,
use the CompletableFuture.join() method to block the calling thread:
lock.unlock().join();
Alternatively, to execute the operation asynchronous and be notified once the lock is acquired in a different
thread, use one of the many completable future callbacks:
lock.unlock().thenRun(() -> System.out.println("Lock released!"));
Copyright © 2013–2016. All rights reserved.