Agent Wranglers

Required

Guard state that concurrent code shares

When two threads, tasks or requests can change the same value, make each read and write one step. Never read a value, wait, then write back a result based on it.

Risk if broken

Data leaked or lost

How to do it

Prefer no shared state, as Pass state in instead of sharing globals says. When state must be shared, make every change under one lock. Examples are asyncio.Lock or threading.Lock in Python, sync.Mutex in Go and synchronized in Java. Single-threaded JavaScript interleaves too, at every await. Cache the promise of a load, not its result, so callers at the same moment share one load. Rows in a database need their own guard, as Make conditional writes says.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

TypeScript example

// Bad: two requests both miss the cache and both load the rates
let rates: Rates | undefined;
async function exchangeRates() {
  if (!rates) rates = await loadRates();
  return rates;
}

// Good: callers share the one load in progress
let ratesLoad: Promise<Rates> | undefined;
function exchangeRates(): Promise<Rates> {
  ratesLoad ??= loadRates();
  return ratesLoad;
}

Python example

# Good: the read and the write happen under one lock
class SeatCounter:
    def __init__(self) -> None:
        self._sold = 0
        self._lock = asyncio.Lock()

    async def sell(self) -> int:
        async with self._lock:
            self._sold += 1
            return self._sold

How to check

A test starts the same change 100 times at once and finds the expected result, such as a count of 100. Go tests run with go test -race. ESLint require-atomic-updates fails assignments that span an await.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/architecture/coupling/guard-shared-state">Agent Wranglers architecture playbook</a>. In code you write, add a comment next to it with the same link.