A distributed lock is mutual exclusion across processes on different machines: exactly one holder, everyone else waits or fails. The mechanism that makes this safe — and the thing this question is really about — is that a distributed lock is a lease, and fencing is what turns "two processes think they hold the lock" from a corruption into a rejected write.
The acquisition model: a process acquires the lock by creating a key in a single-writer store — etcd's lease-based lock, ZooKeeper's ephemeral node, Redis SET key value NX PX 30000. The lock has a TTL/lease, say 10 seconds, renewed by heartbeat while held, deleted on release. The holder then does its critical work and writes results to the system being protected.
Now the failure that makes fencing necessary: the holder's process pauses — a stop-the-world GC for 15 seconds — and its lease expires. Another process acquires the lock legitimately and starts working. The first process resumes, still believing it holds the lock, and writes its results. Two writers, one critical section. This is not a bug you can fix with longer TTLs; pauses are unbounded. It's why "the lock holder believes it is the holder" and "the system accepts its writes" must be separated.
Fencing is the separation. Each successful acquisition returns a monotonically increasing token — etcd's revision, ZooKeeper's session id, a counter — and every write the holder makes must carry that token. The storage layer rejects any write whose token is older than the last token it accepted. The stale holder's writes fail at the storage boundary, no matter what the process believes:
holder A: acquire → token 7 → GC pause (lease expires)
holder B: acquire → token 8 → write accepted (storage last-token = 8)
holder A: resumes → write(token 7) → rejected (7 < 8)The tradeoffs to name: the lock store is a single point of failure — if etcd or ZooKeeper is down, no one can acquire, and uncoordinated failover of the lock store itself can break mutual exclusion; clock skew and pause margins must be budgeted into the lease length, but fencing means the lease only needs to be "probably not expired", not exactly — the token is the hard guarantee; and a bare Redis SET NX PX lock without fencing is mutual exclusion only as long as everything goes perfectly, which is why it's fine for cache stampedes and dangerous for payment dedup. The one-liner: "the lock gives you permission; fencing makes that permission enforceable."