Concurrency
Most concurrency bugs do not appear in tests. They appear at 3am when two requests happen to overlap in just the wrong way. These posts are about isolation levels, race conditions, async vs parallel, deadlocks, and the discipline of writing code that survives concurrent callers.
Why Your Distributed Lock Doesn't Lock
Distributed locks don't provide mutual exclusion. Fencing tokens, GC pauses, clock drift, and why the lock you wrote is actually a polite hint at best.
Read more BackendYour Spring Bean Is Not What You Think It Is
Spring's default bean scope is singleton. The bugs appear when a service holds mutable state, a scoped bean is misused, or ThreadLocal cleanup is skipped.
Read more BackendYour Async Code Is Still Single-Threaded
Async lets one thread do more I/O. It does not let one thread do more CPU. Most async-related performance disappointments come from confusing those two.
Read more BackendTwo Transactions Walk Into a Lock
Deadlocks are not exotic. They are predictable consequences of lock order. Here are the patterns, the fixes, and the eleven characters that ended one outage.
Read more BackendDatabase Isolation Levels Are a Contract, Not a Dial
Isolation levels define which anomalies you tolerate, not how much correctness you get. The SQL standard and what databases implement diverged decades ago.
Read more BackendTransactions Don't Fix Race Conditions
Wrapping code in a transaction doesn't make concurrent operations safe. Here's what transactions guarantee and what race conditions they let slip through.
Read more DatabaseOptimistic vs Pessimistic Locking in JPA
Two JPA strategies for preventing the lost update problem. @Version for optimistic locking, SELECT FOR UPDATE for pessimistic. Real SQL output, working tests.
Read more