Definition · Happens-before, and the Lamport timestampEvent a happens before b, written a → b, if they are on the same process and a is earlier, or a is the send of a message whose receive is b, or there is a chain of such steps from a to b. The Lamport timestamp L assigns each event max(L_local, L_msg) + 1, where L_msg is the stamp carried by a received message and is absent otherwise.
Happens-before is a partial order, not a total one: it is the transitive closure of “same process, earlier” and “sent, then received”, and any two events not connected by such a chain are unrelated by it. A Lamport clock takes that partial order and produces integers consistent with it.
processes A (4 events), B (4 events), C (3 events)
messages A2 → B2 B3 → C2 C1 → A4
A A1 = 1 A2 = 2 A3 = 3 A4 = 4
B B1 = 1 B2 = 3 B3 = 4 B4 = 5
C C1 = 1 C2 = 5 C3 = 6
the three receives, worked
B2 = max(L(B1), L(A2)) + 1 = max(1, 2) + 1 = 3
C2 = max(L(C1), L(B3)) + 1 = max(1, 4) + 1 = 5
A4 = max(L(A3), L(C1)) + 1 = max(3, 1) + 1 = 4
The third receive is the instructive one. The message from C1 carries the stamp 1, which is smaller than A's own counter at that point, so the local clock wins the maximum and A4 becomes 4 rather than 2. A reader who adds one to the message stamp instead of to the maximum gets a stamp that violates A's own process order, which is the first thing to check when a diagram comes out wrong.
The direction that fails
L(B1) = 1 and L(A2) = 2, so L(B1) < L(A2)
but is there a chain B1 → … → A2 ?
B1 → B2 → B3 → C2 → C3 and C3 sends nothing
the only message into A is from C1, which B cannot reach
so no: B1 and A2 are concurrent
on this diagram
ordered pairs, a → b 32
pairs with L(a) < L(b) and a NOT before b 17
Seventeen against thirty-two is not a rare corner case, it is a third of the ordered-looking pairs on a small diagram. A Lamport stamp is a one-dimensional summary of a partial order, and the information it cannot carry is exactly the information about which pairs are unrelated.
Example · Why a total order is useful anywayBreak ties by process identifier and the stamps give a total order on all events, consistent with causality. That is enough for a distributed mutual-exclusion queue, for a deterministic replay of a log, and for any rule of the form “process requests in a fixed order that everyone agrees on”. What it is not enough for is detecting that two updates were concurrent, because the total order cheerfully orders pairs that nothing ordered — and a merge that trusts it will silently pick a winner between two updates that should both have been kept.
So the honest summary is: Lamport stamps are a cheap way to get an order everyone agrees on, and a wrong way to decide whether one event caused another. One integer per process is all they cost and it is also all they can carry. “Vector Clocks and Concurrency” spends n integers instead and gets the missing direction back.