Memory as a database
Software transactional memory lets you wrap a block of reads and writes in a transaction that appears to run atomically. You describe what should happen; the runtime handles isolation, much like a database does for rows.
Optimistic execution
STM is usually optimistic. A transaction runs without locks, recording the versions of every location it read and buffering its writes. At commit time it validates: if any value it read changed, the transaction retries from scratch on fresh data. If nothing changed, the buffered writes are applied atomically.
Why it composes
Lock based code is hard to combine because two correct locked functions can deadlock when nested. STM transactions compose: a transaction that calls another simply extends the same atomic block, with no lock ordering to get wrong.
The costs
- Retries waste work under high contention; a hot location can livelock.
- Transactions must be free of irreversible side effects, because a retry would repeat them. Input and output do not belong inside a transaction.
Blocking elegantly
Many STMs offer a retry primitive that parks a transaction until one of the values it read changes, turning busy waiting into efficient blocking.
Key idea
STM runs blocks optimistically, validates reads at commit, and retries on conflict, giving composable atomicity without explicit locks.