api: "YAML JSON TOON Database" version: 1.0.0 format: toon dataset: id: 354 slug: concurrency-design-patterns title: "Concurrency Design Patterns" description: "Patterns for multi-threaded programming: Producer-Consumer, Reader-Writer, Thread Pool, Future/Promise, Reactor, Monitor, Scheduler." category: "Design Patterns" category_slug: design-patterns tags: "design-patterns,concurrency,multithreading,producer-consumer,thread-pool" view_count: 6 created_at: 1781275786 updated_at: 1781275786 data: patterns [7]{name,problem,solution_brief,key_components,benefits,pitfalls,language_examples}: "Producer-Consumer (Bounded Buffer)","Producers generate data; consumers process it. Need to coordinate so consumers don't read from empty buffer, producers don't write to full buffer.","Use a fixed-size queue as buffer. Producers block when full; consumers block when empty. Synchronized access ensures thread safety.",["Shared buffer\/queue with bounded capacity","Producer threads (generate items, put in buffer)","Consumer threads (take items from buffer, process)","Synchronization mechanism (mutex + condition variables\/semaphores)"],"Decouples producers and consumers, smooths load variations, enables pipelining, buffers spikes in production/consumption rates.","Deadlock if synchronization incorrect, priority inversion possible, buffer size tuning critical (too small causes blocking; too large uses memory), consumers may starve if producers fast.",{"Java":"BlockingQueue interface (ArrayBlockingQueue, LinkedBlockingQueue); put() and take() block automatically.","Python":"queue.Queue (thread-safe), producer calls put(), consumer calls get()","C++":"std::queue with std::mutex + std::condition_variable, or boost::lockfree::queue","Go":"Channels (chan) with buffered or unbuffered; goroutines communicate naturally"} "Reader-Writer Lock","Data structure frequently read, rarely written. Mutex allows only one thread at a time (even for readers), causing unnecessary contention.","Allow multiple readers simultaneous access, but writers get exclusive access. Readers don't block each other; writers block both readers and other writers.",["Read lock (shared): multiple threads can hold simultaneously","Write lock (exclusive): only one thread, no readers","Lock upgrade\/downgrade (optional)","Reader counter or reference count"],"Better throughput for read-heavy workloads, scales well with many readers, writers get exclusive access to prevent dirty reads.","Writer starvation if continuous readers arrive, reader-writer deadlock if not careful, higher overhead than simple mutex for write-heavy cases, complex to implement correctly.",{"Java":"java.util.concurrent.locks.ReentrantReadWriteLock; readLock().lock(), writeLock().lock()","C++":"std::shared_mutex (C++17); std::shared_lock for readers, std::unique_lock for writers","Python":"threading.RLock doesn't support readers; use read_write_lock third-party or multiprocessing.Manager","C#":"ReaderWriterLockSlim; EnterReadLock(), EnterWriteLock()"} "Thread Pool","Creating/destroying threads is expensive (OS resources, context switching). Spawning thread per task leads to overhead and uncontrolled resource usage.","Pre-create a fixed number of worker threads and queue tasks. Workers wait for tasks; when task arrives, idle worker executes it. Reuses threads across many tasks.",["Thread pool (fixed size worker threads)","Task queue (work queue, blocking)","Worker loop: while (true) { task = queue.take(); execute(task); }","Saturation strategy (queue full: reject, block, or spawn new thread)"],"Reduces thread creation overhead, bounds resource usage, improves response time (threads ready), enables task prioritization and scheduling.","Queue can become bottleneck, thread starvation if pool too small, deadlocks if tasks wait on other queued tasks, tasks may block pool threads indefinitely.",{"Java":"ExecutorService, ThreadPoolExecutor, Executors.newFixedThreadPool(n), CompletableFuture with custom executor","Python":"concurrent.futures.ThreadPoolExecutor, submit(task) returns Future","C#":"Task Parallel Library (TPL), ThreadPool.QueueUserWorkItem, Task.Run","C++":"Boost.Asio thread pool, Intel TBB task scheduler, custom with std::thread + std::queue"} "Future / Promise","Need to run computation asynchronously and retrieve result later. Caller shouldn't block waiting for result; needs way to check completion or get result when ready.","Future is a placeholder for result of async operation. Promise is writeable handle that fulfills the future. Caller gets future immediately, checks isDone(), calls get() to block or poll.",["Future (read-only): isDone(), get(timeout), cancel()","Promise (write-only): setValue(result), setException(err)","Completion callback (optional): then(), addListener()","Cancellation mechanism"],"Avoids blocking threads, enables composition of async operations, simplifies error propagation, clean API for async results.","Blocking get() defeats purpose (use callbacks instead), exceptions must be captured in Future, cancellation not always supported, many small async tasks create overhead.",{"Java":"CompletableFuture (most powerful), Future (older), CompletableFuture.supplyAsync(...)","JavaScript":"Promise (then\/catch), async\/await syntactic sugar","Python":"concurrent.futures.Future, asyncio.Future","C#":"Task (Task is Future without result); async\/await"} "Reactor Pattern","Server handling many simultaneous connections (e.g., web server). One thread per connection (thread-per-connection) doesn't scale (thousands of connections = thousands of threads).","Single (or few) thread(s) use non-blocking I/O and demultiplexer (select/poll/epoll/kqueue) to monitor multiple sockets. When I/O event occurs, dispatcher calls appropriate handler callback.",["Event demultiplexer (select, poll, epoll, kqueue)","Event handlers (callback objects)","Reactor (main loop: wait for events -> dispatch to handlers)","Non-blocking I\/O sockets"],"Scales to thousands of connections with few threads, efficient resource usage (no thread overhead), good for I/O-bound services.","Complex to implement correctly, callbacks can lead to spaghetti code (use coroutines/fibers), CPU-bound tasks still block reactor, edge-triggered vs level-triggered pitfalls.",{"Java":"NIO (Non-blocking I\/O), Selector, SocketChannel; Netty framework implements Reactor","Python":"selectors module, asyncio event loop, Twisted framework","Node.js":"libuv event loop (epoll\/kqueue\/IOCP) built-in; all I\/O non-blocking","C++":"Boost.Asio, libevent, libuv"} "Monitor (Monitor Object)","Multiple threads access shared data; need to ensure mutual exclusion and coordinate access. Condition variables and mutexes scattered lead to error-prone code.","Encapsulate shared data with its synchronization (mutex) and condition variables inside a monitor object. Only one thread can execute any monitor method at a time. Condition variables allow threads to wait for conditions.",["Mutual exclusion lock (implicit in monitor entry)","Condition variables (wait\/signal)","Shared data (private to monitor)","Procedures\/methods (only one active at a time)"],"Simplifies synchronization (acquire/release implicit), prevents unsynchronized access (all accesses go through monitor), high-level abstraction, reduces race conditions.","Can cause performance bottleneck if monitor too large (coarse-grained), conditional waiting can lead to missed signals or spurious wakeups, deadlocks possible if monitor calls external code.",{"Java":"synchronized methods\/blocks (built-in monitor), wait()\/notify()\/notifyAll() on object","Python":"threading.Lock + Condition, but no built-in monitor keyword; can use with statement","C#":"lock statement (Monitor.Enter\/Exit), Monitor.Wait\/Pulse","C++":"No built-in monitor; implement with std::mutex + std::condition_variable"} "Scheduler Pattern","Need to execute tasks at specific times (cron jobs), at fixed intervals, or after delays. Managing timers and thread pools manually is complex.","Central scheduler coordinates task execution based on time criteria. Maintains priority queue of scheduled tasks; scheduler thread manages timers and dispatches tasks to worker threads when due.",["Task (callable with execution time, priority, periodicity)","Schedule queue (priority queue ordered by next execution time)","Timer mechanism (wait\/notify, delay queue, wheel timer)","Worker pool (optional, execute tasks asynchronously)","Scheduling strategies (fixed-rate, fixed-delay, cron)"],"Centralized task management, efficient timer management (single thread for many timers), supports recurring tasks, cron-like scheduling, easy to pause/cancel/reschedule.","Scheduler thread single point of failure, task overruns can backlog, clock drift affects timing, distributed systems need distributed scheduler (e.g., Quartz, Celery).",{"Java":"ScheduledExecutorService, Timer\/TimerTask, Quartz Scheduler, Spring @Scheduled","Python":"sched module, APScheduler, Celery beat, cron jobs via OS","C#":"System.Threading.Timer, Quartz.NET, Hangfire","Node.js":"node-cron, setInterval\/setTimeout (single-threaded)"}