Concurrency & Performance
29 guides
Locks, races, deadlocks and the performance problems that only show up under load.
Optimistic lockingOptimistic locking takes no lock at all — it records the version a reader saw and refuses the write if that version has moved, turning a lost update into a detectable conflict.Concurrency9 min readWith code examplePessimistic lockingPessimistic locking prevents conflict rather than detecting it: the reader takes an exclusive row lock up front, so no other writer can reach the row until the transaction ends.Concurrency9 min readWith code exampleRace conditionsA race condition exists when the correctness of a result depends on the relative timing of operations that the system is free to interleave however it likes.Concurrency9 min readWith code exampleDeadlockA deadlock is a cycle in the wait-for graph: every participant holds a resource the next one needs, so none can proceed and none will ever give up.Concurrency8 min readWith code exampleLivelock and starvationLivelock is motion without progress — threads repeatedly retry and repeatedly undo each other; starvation is a thread that is ready to run but never gets the resource it needs.Concurrency9 min readWith code exampleThread safetyA class is thread-safe when it behaves correctly under concurrent access from multiple threads with no additional coordination from the caller — a claim about invariants, not about keywords.Concurrency8 min readWith code exampleMemory visibility and volatile`volatile` guarantees that a write is visible to every subsequent read and that accesses are not reordered around it — visibility and ordering, never atomicity of a compound operation.Concurrency9 min readWith code exampleAtomic operations and CASCompare-and-swap is a single hardware instruction that writes a new value only if the current value is still the one you read — the primitive every lock-free algorithm and every lock is built on.Concurrency9 min readWith code exampleMutex vs semaphoreA mutex has an owner and grants exclusive access; a semaphore is a counter of permits with no owner — which is why one can be reentrant and released only by its holder, and the other cannot.Concurrency8 min readWith code exampleRead-write locksA read-write lock lets any number of readers proceed together but excludes all readers while a writer holds it — profitable only when reads dominate and each read is long enough to pay for the bookkeeping.Concurrency9 min readWith code exampleThread-pool sizingA thread pool is sized from the work it performs and the resources it consumes, not from a memorised multiple of CPU cores.Concurrency3 min readWith code exampleProducer–consumer problemThe producer–consumer pattern decouples work creation from work processing through a bounded buffer whose full and empty states must be synchronised.Concurrency3 min readWith code exampleImmutability and concurrencyAn immutable object never changes after construction, so readers can share it without coordinating every field access with a writer.Concurrency3 min readLock-free programmingA lock-free algorithm guarantees system-wide progress: even if threads are delayed, some operation completes, usually through atomic compare-and-set loops.Concurrency3 min readWith code exampleVirtual threads vs platform threadsVirtual threads make blocking, thread-per-task code cheap by multiplexing many user-mode threads over a smaller set of carrier threads; they do not make CPU work free.Concurrency4 min readDouble-checked lockingDouble-checked locking avoids taking a lock on every read only when the shared reference has safe publication semantics and construction cannot be observed halfway through.Concurrency3 min readWith code exampleHappens-before relationshipHappens-before is the memory-model relation that guarantees visibility and ordering between actions across threads; wall-clock order alone does not.Concurrency3 min readThread-local storageThread-local storage gives each thread its own value, avoiding sharing, but pooled threads make cleanup and context lifetime part of correctness.Concurrency3 min readWith code exampleCaching strategiesCaching strategies keep reusable results closer to callers or computation so latency and backend load fall within an explicit freshness and invalidation policy.Performance3 min readCache invalidationCache invalidation removes or versions cached data when the source changes so readers do not observe stale state beyond the allowed policy.Performance3 min readCache stampedeA cache stampede occurs when many callers miss or expire the same key and simultaneously load the origin, overwhelming the very dependency the cache was meant to protect.Performance3 min readWrite-through vs write-back cacheWrite-through caching updates the cache as part of a write path, while write-back caching acknowledges or buffers writes before the source of truth is updated.Performance3 min readBackpressureBackpressure keeps producers from creating work faster than consumers can safely process it by bounding queues, slowing admission, or rejecting work.Performance3 min readCircuit breakerA circuit breaker stops sending work to a failing dependency for a bounded period, giving the dependency and the caller a chance to recover instead of multiplying the outage.Performance3 min readBulkhead patternThe bulkhead pattern isolates resource pools or concurrency budgets so one workload can fail or saturate without consuming capacity needed by others.Performance3 min readRetry with exponential backoffExponential backoff spaces retries farther apart after transient failure, while jitter prevents many clients from retrying in synchrony.Performance3 min readRedis vs MemcachedMemcached is a simple distributed cache; Redis offers richer data structures and durability options. Compare eviction, persistence, atomicity, and failure behaviour.Performance3 min readRead replica vs CacheRead replicas preserve query semantics with replication lag; caches trade freshness and rebuild complexity for very low latency. Choose based on correctness and access patterns.Performance3 min readHorizontal scaling vs Vertical scalingVertical scaling is the simplest first move; horizontal scaling wins when one machine is a capacity or availability limit. Compare state, coordination, and cost.Performance3 min read