Gronex
Log in

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.ConcurrencyPessimistic 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.ConcurrencyRace 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.ConcurrencyDeadlockA 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.ConcurrencyLivelock 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.ConcurrencyThread 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.ConcurrencyMemory 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.ConcurrencyAtomic 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.ConcurrencyMutex 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.ConcurrencyRead-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.ConcurrencyThread-pool sizingA thread pool is sized from the work it performs and the resources it consumes, not from a memorised multiple of CPU cores.ConcurrencyProducer–consumer problemThe producer–consumer pattern decouples work creation from work processing through a bounded buffer whose full and empty states must be synchronised.ConcurrencyImmutability and concurrencyAn immutable object never changes after construction, so readers can share it without coordinating every field access with a writer.ConcurrencyLock-free programmingA lock-free algorithm guarantees system-wide progress: even if threads are delayed, some operation completes, usually through atomic compare-and-set loops.ConcurrencyVirtual 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.ConcurrencyDouble-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.ConcurrencyHappens-before relationshipHappens-before is the memory-model relation that guarantees visibility and ordering between actions across threads; wall-clock order alone does not.ConcurrencyThread-local storageThread-local storage gives each thread its own value, avoiding sharing, but pooled threads make cleanup and context lifetime part of correctness.ConcurrencyCaching strategiesCaching strategies keep reusable results closer to callers or computation so latency and backend load fall within an explicit freshness and invalidation policy.PerformanceCache invalidationCache invalidation removes or versions cached data when the source changes so readers do not observe stale state beyond the allowed policy.PerformanceCache 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.PerformanceWrite-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.PerformanceBackpressureBackpressure keeps producers from creating work faster than consumers can safely process it by bounding queues, slowing admission, or rejecting work.PerformanceCircuit 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.PerformanceBulkhead patternThe bulkhead pattern isolates resource pools or concurrency budgets so one workload can fail or saturate without consuming capacity needed by others.PerformanceRetry with exponential backoffExponential backoff spaces retries farther apart after transient failure, while jitter prevents many clients from retrying in synchrony.PerformanceRedis vs MemcachedMemcached is a simple distributed cache; Redis offers richer data structures and durability options. Compare eviction, persistence, atomicity, and failure behaviour.PerformanceRead 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.PerformanceHorizontal 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.Performance