šŸ”€ Concurrency Patterns (Java + Go)

PatternProblemJavaGoOrbit usage
Producer–consumerDecouple production from consumptionBlockingQueueBuffered channelEngine → task queue → workers
Worker poolBounded parallelismThreadPoolExecutor / virtual threads + SemaphoreN goroutines reading one channelStep runners
PipelineStage-by-stage streamingCompletableFuture chains, ReactorChained channelsIngestion: parse → chunk → embed → upsert
Fan-out / fan-inParallelize and mergeinvokeAll, structured concurrencyMultiple goroutines + merge channelmap step, parallel sub-agents
Bounded concurrency (semaphore)Cap concurrent callsSemaphoreBuffered channel as a semaphore, x/sync/semaphoreMax concurrent LLM calls per tenant
Futures / promisesAsync resultsCompletableFutureChannel of results, errgroupParallel tool calls
Structured concurrencyChild tasks scoped to a parent; cancel siblings on failureStructuredTaskScope (check its status in your JDK)errgroup.WithContext ⭐Parallel steps: fail fast
Cancellation / deadlinesStop wasted workFuture.cancel, interrupts⭐ context.ContextRun cancellation propagates to LLM streams
Request coalescing (singleflight)Dedupe identical concurrent workCaffeine AsyncLoadingCachex/sync/singleflight ⭐Cache stampede protection in the gateway
BackpressureDon’t let producers overwhelm consumersBounded queues + rejection policy, Reactive StreamsBlocking sends on bounded channelsStreaming tokens to slow clients; 429 admission
Rate limitingSmooth the request rateGuava RateLimiter, bucket4jx/time/rateProvider RPM/TPM limits
ActorState owned by one thread, message passingAkka/PekkoA goroutine owning state + an inbox channelPer-run coordinator
Reactor (event loop)Many connections, few threadsNettyGo netpoller (hidden)orbit-stream
Read–write lockMany readers, few writersReentrantReadWriteLock, StampedLocksync.RWMutexProvider config registry
Copy-on-writeLock-free reads of rarely-changing dataCopyOnWriteArrayListatomic.Pointer[T] swapRouting table hot reload
Lock stripingReduce contentionCHM bins, LongAdderSharded maps with N mutexesIn-memory quota counters
Optimistic concurrency (CAS / version)Avoid locks under low contentionAtomicReference, JPA @Versionatomic.CompareAndSwap, SQL version columnsWorkflow publish, lease renewals
Double-checked lockingLazy initNeeds volatile; prefer the holder idiomsync.OnceLazy provider clients
Thread confinementNo sharing, no locksThreadLocal, scoped valuesGoroutine-local by designRequest context
Immutable objectsSafe sharingRecordsValue types, unexported fieldsWorkflow definitions after publish
Guarded suspension / condition waitWait until a condition holdsCondition.awaitsync.Cond / channelsWaiting for a lease/slot
HeartbeatLivenessScheduled executortime.Ticker goroutineWorker lease renewal

šŸ”¬ Katas

  • Pipeline with a bounded channel per stage; prove backpressure (a slow last stage → producers block, memory stays flat)
  • errgroup fan-out with cancel-on-first-error vs Java structured concurrency: the same behavior, compared
  • singleflight: 1,000 concurrent identical cache misses → 1 upstream call
  • Copy-on-write config reload under 10k RPS without locks
  • Actor-style run coordinator in Go vs lock-based in Java: compare complexity and bugs