advanced24 min studyLesson 232 in Engineering

Order known dependencies with logical counters

Construct happened-before order and Lamport updates without interpreting counter differences as durations or reversed implications as causality.

On this page

What you’ll understand

  • Build happened-before from local order, message edges, and transitivity.
  • Apply increment and max-plus-one clock updates consistently.
  • Separate a causality-preserving total order from evidence of a causal relationship.

A service writes a record and sends another service a message about it. Even when their wall clocks disagree, the receiving event cannot precede the corresponding send in the execution's dependency order. Logical clocks preserve this kind of relationship using counters rather than calibrated seconds. Their power comes from a deliberately narrow promise: known causal precedence makes the assigned value increase. Their limitation is equally useful: increasing values alone do not reveal which events actually influenced one another.

Define the relation before assigning timestamps

Model each participant as a sequence of recorded events. Earlier events on one participant precede its later events; sending a particular message precedes receiving that same message; and these relationships compose transitively. The resulting happened-before relation is a strict partial order. Events with neither direction related are concurrent in this model. That term describes missing causal order, not necessarily simultaneous physical execution. Two independent machines can perform events hours apart and still have no modeled message path connecting them. The answer also depends on where instrumentation defines the send, receive, and local events.

A participant is an ordered execution context, not automatically every thread sharing one process identifier. If a program has several concurrent threads, the local-order edges must reflect the actual synchronization model rather than an invented sequence from merged logs. An external dependency omitted from the model can also hide a real influence. State which communication channels are represented. A user copying a result between applications can create a meaningful real-world dependency that a narrow message-only trace misses. Logical time correctly represents the specified event model; it cannot manufacture knowledge of events that were never propagated or recorded.

a→b ∧ b→c⟹a→ca\to b\ \land\ b\to c\quad\Longrightarrow\quad a\to c
The arrow is happened-before over explicitly modeled events. It is a transitive ordering relation, not a numerical duration or a claim that unrelated events share one physical instant.↔ Scroll wide equations horizontally.

Implement the clock condition

Maintain a nonnegative logical counter at each participant. For this lesson's convention, increment before every local or send event, and attach that event's counter to the message. For a receive event carrying remote value m, replace the local counter by one more than the maximum of its previous value and m. The exact bookkeeping convention may vary, but both local sequence and send-to-receive edges must increase strictly. Consistently applying one convention makes examples auditable; mixing an increment-before convention with an increment-after diagram can produce misleading off-by-one claims.

The clock condition says that happened-before implies a smaller timestamp. Its converse does not hold. An independent participant might have executed more local events and therefore have a larger counter without learning anything about the other participant. A gap of one hundred logical units is not a hundred milliseconds, messages, or missing log entries in the global execution. It can partly reflect jumping forward after receiving a large value. Keep counter state durable or introduce a well-defined incarnation when required across restart, and prevent overflow from silently turning a later event into a smaller ordinary integer.

Lreceive=max⁡(Lprevious,Lmessage)+1,a→b⇒L(a)<L(b)L_{\mathrm{receive}}=\max(L_{\mathrm{previous}},L_{\mathrm{message}})+1,\qquad a\to b\Rightarrow L(a)<L(b)
L values are dimensionless logical counters. The update assumes the stated receive-event convention and sufficiently represented counters; numerical ordering alone does not imply a happened-before path.↔ Scroll wide equations horizontally.

A deterministic tie-break adds order, not knowledge

Two concurrent events can receive the same logical value. Adding a stable participant identifier supplies a deterministic lexicographic tie-break, producing a total order that extends happened-before. This can be useful for a protocol's arbitration rule, but it does not reveal the true physical order of concurrent events. Different legitimate identifiers or counter histories can produce different extensions. Nor does attaching timestamps alone implement reliable total-order delivery: a receiver still needs a protocol for learning when no lower-ordered event remains in flight. Representation, delivery, and application conflict resolution are separate design choices.

The modular lab demonstrates a representation hazard rather than a distributed clock. Reset, set both modulus m=8 and additive step a=1, predict what follows residue seven, then use Play or Step. Playback selects successive additions and eventually wraps to zero. Compare a fresh run only after another Reset and re-setting both controls. Ordinary numerical comparison would now place the later residue before an earlier one. Real Lamport implementations need sufficient counter space or an explicit rollover and incarnation scheme; the lab provides no messages, receive updates, or correctness protocol for handling that rollover.

A message makes the receiver jump

A and B start with counters zero. A performs one local event and then sends a message. B has already performed four independent local events before receiving that message. Use the increment-before-event convention.

  1. A’s local event receives value 1; its send receives value 2, which is carried by the message. B’s four local events leave its counter at 4.

  2. B’s receive updates its counter to max(4, 2)+1=5. The actual send-to-receive edge has timestamps 2 and 5, preserving the clock condition.

  3. B’s earlier local event with value 4 still has no specified happened-before relation with A’s send at value 2. The inequality 2<4 cannot supply the missing communication edge.

The result

The receive is stamped 5, but larger counter values at B do not retrospectively establish dependencies for its earlier independent work.

Explore the model

Interactive lab

Interactive lab · modular

Watch an ordinary integer order fail at wraparound

Reset, set both modulus m=8 and additive step a=1, predict the transition after residue 7, then Play or Step. Playback uses n=floor(2t); each Step advances one addition. This additive modular orbit is not a Lamport clock or a receive-message simulation.

Watch an ordinary integer order fail at wraparoundAddition modulo m starts at zero: rₙ = na mod m. Playback advances two additions per second. The orbit has period m/gcd(m,a), including period one for a = 0. This is not a cryptographic security test or a primality algorithm. Current readings: Residue r0: 0; Orbit period · m/gcd(m,a): 12; Distinct residues visited: 1 of 12. All parameters are adjustable with the labeled controls below.Repeated addition modulo 12: the current residue is 0, and the orbit period is 12.01234567891011+ 5mod 12An additive orbitn = 0rₙ = 0Period = 12Cycle starts at 0:0 → 5 → 10 → 3 →8 → 1 → 6 → 11 →4 → 9 → 2 → 7 → 0Exact residues · two additions per second
Additive orbitCurrent residue / next edge
Residue r0
0
Orbit period · m/gcd(m,a)
12
Distinct residues visited
1 of 12
t = 0 s

Addition modulo m starts at zero: rₙ = na mod m. Playback advances two additions per second. The orbit has period m/gcd(m,a), including period one for a = 0. This is not a cryptographic security test or a primality algorithm. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forA later wrapped residue can be numerically smaller. A distributed timestamp representation needs an explicit overflow policy rather than assuming modular values preserve ordinary increasing order.

Check your understanding

Two events have Lamport values 12 and 19. Which statement follows from those values alone?

Try it yourself

A receiver has local counter 9 and accepts a message stamped 14. What receive value follows? Can that new value be converted to a physical deadline?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Apply max-plus-one, then distinguish an event-order counter from an elapsed-time clock.

Compare with the solution

The receive value is 15. It establishes an ordering after the message’s send under the model, but has no calibrated duration unit and cannot be interpreted as a physical deadline without an additional clock contract.

Take it with you

  • Happened-before is a partial order built from defined event edges.
  • Lamport values preserve causal order but do not characterize it in both directions.
  • Tie-breaks and rollover policies add protocol decisions, not physical-time knowledge.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.