Distributed Lock
This page is part of the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at README.md, and llms.txt lists every page.What it shows
ILatticeLockGrain is a single-cluster, FIFO-fair distributed lock / lease keyed by
name. Because an Orleans grain activation is single-threaded and processes its inbox
in arrival order, a grain keyed by a lock name is a natural FIFO mutual-exclusion
point - and this primitive gets the failure modes right: monotonic fencing
tokens (so a superseded holder is detectable by the resource it guards) and
bounded leases (so a crashed holder cannot wedge the lock forever).
This sample demonstrates:
- Acquire, renew, release - and the strictly-increasing fencing token stamped on every grant.
- Non-blocking try-acquire -
nullwhile the lock is held, granted after it is released. - FIFO blocking - a second caller queued behind the holder is granted the instant the holder releases, with a strictly higher fencing token.
Run it
dotnet run --project samples/DistributedLock
Expected output
== DistributedLock sample ==
1) Acquiring the lock (30s lease, willing to wait 5s)...
granted, fencing token = 1
status: held=True queueDepth=0
renewed the lease.
released. The next caller can acquire immediately.
2) Holder acquired, fencing token = 2.
TryAcquire while held -> null (skipped)
TryAcquire after release -> granted, fencing token = 3
3) First holder acquired, fencing token = 4.
a second caller is queued: queueDepth=1
first holder releases...
queued waiter granted, fencing token = 5 (strictly higher).
Done.
When to use
- You need to serialize a cluster-wide critical section: a singleton job, a leader election, or an externally-visible resource that needs one writer at a time.
- You want a lock that survives a crashed holder (bounded lease reclamation) and gives you a fencing token to forward to the guarded resource, so a paused holder that lost the lock can no longer write.
When not to use
- To coordinate mutual exclusion across clusters. The lock is single-cluster: for a given name each Orleans cluster keeps its own independent activation, so two clusters can grant the same lock at once and their fencing tokens are not comparable. When a mutation must be atomic across clusters, write it to a tree (see atomic writes or the atomic action coordinator), whose commit replicates to every cluster the tree replicates to.
- To make a batch of key writes atomic. That is a different problem than mutual exclusion - use atomic writes (or, to mix a tree write with other effects, the atomic action coordinator).
- As a general coordination signal off
GetStatusAsync: that snapshot is for diagnostics only. Only the fencing token from an actual grant is authoritative.