awesome-everything RU
↑ Back to the climb

Distributed Systems

Clocks: code and trace reading

Crux Read clock-update code and event traces — Lamport increment, vector-clock merge, happens-before comparison, and concurrency detection — and predict the result.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min

Logical clocks are tiny pieces of code with subtle correctness rules. Read each update routine and event trace, then pick the answer a senior engineer would defend in review — where the bug, the order, or the concurrency verdict actually lives.

Goal

Practise the core operations of logical clocks in code: a Lamport increment on send and receive, a vector-clock merge, the happens-before comparison, and detecting that two events are concurrent rather than ordered.

Snippet 1 — the Lamport receive

class LamportClock:
    def __init__(self):
        self.t = 0

    def on_local_event(self):
        self.t += 1
        return self.t

    def on_send(self):
        self.t += 1
        return self.t            # piggyback self.t on the message

    def on_receive(self, msg_t):
        self.t = self.t          # <-- BUG candidate
        self.t += 1
        return self.t
Quiz

The receive handler ignores msg_t. What invariant does this break, and what is the fix?

Snippet 2 — the vector-clock merge

def merge_receive(local, msg_vec, my_id):
    # local and msg_vec are dicts: node_id -> counter
    merged = {}
    for node in set(local) | set(msg_vec):
        merged[node] = max(local.get(node, 0), msg_vec.get(node, 0))
    merged[my_id] += 1
    return merged
Quiz

This receive merge is correct. Which statement captures why the elementwise max plus a single self-increment is exactly right?

Snippet 3 — comparing two vector clocks

def compare(a, b):
    # returns 'before', 'after', or 'concurrent'
    le = all(a.get(k, 0) <= b.get(k, 0) for k in set(a) | set(b))
    ge = all(a.get(k, 0) >= b.get(k, 0) for k in set(a) | set(b))
    if le and not ge: return 'before'      # a happens-before b
    if ge and not le: return 'after'
    if le and ge:     return 'equal'
    return 'concurrent'
A = {n1: 2, n2: 1, n3: 0}
B = {n1: 1, n2: 1, n3: 4}
Quiz

What does compare(A, B) return for these two vectors, and what does it mean for conflict resolution?

Snippet 4 — the event trace

P1: a(send m1)            Lamport: a=1
P2: b(recv m1) -> c(send m2)
P3: d(recv m2)
P1: e(local)              Lamport: e=2
Quiz

Using happens-before over this trace, what is the relationship between e on P1 and d on P3?

Recap

The clock operations are small but unforgiving: a Lamport receive must take max(local, msg) + 1 or it can stamp a receive earlier than its send; a vector-clock receive takes the elementwise max and bumps only its own component; comparing vectors is componentwise, and when each side leads on some node the events are concurrent and must be kept as siblings. And no Lamport number ordering implies causality without a connecting message path. Read the code and the trace, then decide order vs concurrency from the causal structure, not the raw integers.

Continue the climb ↑Clocks: build a conflict-detecting store
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.