[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6WZDV7AQ87NPMYN3HZVRRY4":3,"skill-same:01M6WZDV7AQ87NPMYN3HZVRRY4":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":14,"repositoryHtmlUrl":54,"repositoryHomepageUrl":55,"ownerHtmlUrl":56,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":57,"install":58,"resources":71},"01M6WZDV7AQ87NPMYN3HZVRRY4","concurrency-patterns",null,"Concurrency and parallelism patterns — async\u002Fawait, threads, actors, channels, deadlock prevention. Use when choosing a concurrency model, designing concurrent or parallel pipelines, debugging deadlocks or race conditions, or reasoning about shared state and backpressure.","projectious-work\u002Fprocesskit","projectious-work","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F263889726?v=4","01M6N97TJJ118WQ35CHRV8RD0E","projectious.work","01M6N97TPWJPF0BMKYQ4PBY5W8",0,"MIT","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.18.1\u002Fcontext\u002Fskills\u002Fengineering\u002Fconcurrency-patterns\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"concurrency patterns","concurrency","patterns","pipelines","when","v1","threads","about","channels","shared","async","debugging","use","work","parallel","model","prevention","engineering","state","reasoning","2026-11-10 10:12:30",false,"---\nname: concurrency-patterns\ndescription: |\n  Concurrency and parallelism patterns — async\u002Fawait, threads, actors, channels, deadlock prevention. Use when choosing a concurrency model, designing concurrent or parallel pipelines, debugging deadlocks or race conditions, or reasoning about shared state and backpressure.\nmetadata:\n  processkit:\n    apiVersion: processkit.projectious.work\u002Fv1\n    id: SKILL-concurrency-patterns\n    version: \"1.1.0\"\n    created: 2026-04-06T00:00:00Z\n    category: engineering\n---\n\n# Concurrency Patterns\n\n## Intro\n\nConcurrency is about structuring a program to handle multiple tasks;\nparallelism is about running them on multiple cores simultaneously.\nPick the model that matches the bottleneck (I\u002FO vs CPU), prefer\nmessage passing over shared state, and design for backpressure from\nday one.\n\n## Overview\n\n### Concurrency vs parallelism\n\nConcurrency is a structuring technique — interleaving tasks so the\nprogram makes progress on many things at once, even on a single core.\nParallelism is true simultaneous execution across multiple cores.\nChoose based on the bottleneck:\n\n- **I\u002FO-bound** (network, disk, database): use concurrency\n  (async\u002Fawait or green threads). One thread can multiplex thousands\n  of connections.\n- **CPU-bound** (computation, data processing): use parallelism (OS\n  threads or processes) so all cores are busy.\n- **Mixed**: combine both — async for I\u002FO at the edges, a thread or\n  process pool for the CPU-heavy core.\n\n### Choosing a concurrency model\n\n| Model | Best for | Watch out for |\n|---|---|---|\n| **async\u002Fawait** | High-concurrency I\u002FO (web servers, API clients) | Don't block the event loop with CPU work |\n| **OS threads** | CPU-bound parallelism, simple shared state | Per-thread stack overhead, limited scalability |\n| **Green threads \u002F goroutines** | Massive concurrency with simple code (Go, Erlang) | Scheduler quirks, blocking FFI calls |\n| **Actors** | Distributed systems, fault isolation | Ordering guarantees, debugging |\n| **Channels \u002F message passing** | Decoupled producer-consumer pipelines | Backpressure, channel capacity |\n| **Thread pool + work queue** | Bounded parallelism for batch jobs | Queue sizing, graceful shutdown |\n\n### Managing shared state\n\nPrefer message passing. When shared state is unavoidable, pick the\nright primitive:\n\n- **Mutex** — one writer or one reader at a time. Use for general\n  shared mutable state.\n- **RwLock** — many concurrent readers or one exclusive writer. Use\n  when reads vastly outnumber writes (configuration, lookup tables).\n- **Atomics** — lock-free updates for simple values like counters and\n  flags. Cheapest option when it fits.\n- **Concurrent data structures** — ConcurrentHashMap, DashMap, sync\n  collections — let the library handle synchronization for you.\n\nHold locks for the shortest possible duration. Never perform I\u002FO or\nallocations while holding a lock. Prefer scoped lock guards\n(`Arc\u003CMutex\u003CT>>`, `synchronized` blocks) over manual lock\u002Funlock.\n\n### Backpressure\n\nWhen producers outpace consumers, unbounded queues cause memory\nexhaustion. Design backpressure in from the start:\n\n- **Bounded channels** — block or reject the producer when full.\n- **Rate limiting** — control the inbound rate at the edge.\n- **Load shedding** — drop low-priority work under pressure.\n- **Reactive streams** — propagate demand signals upstream so the\n  producer slows down naturally.\n\n```go\n\u002F\u002F Go: bounded channel provides natural backpressure\njobs := make(chan Job, 100)  \u002F\u002F blocks producer when 100 items queued\n```\n\n### Example workflows\n\n- **I\u002FO-bound web scraper:** async\u002Fawait with a semaphore capping\n  concurrency (e.g. 50 simultaneous requests). `tokio::spawn` plus\n  `tokio::sync::Semaphore` in Rust, or `asyncio.gather` with\n  `asyncio.Semaphore` in Python.\n- **Bulk record processing:** fan-out \u002F fan-in pipeline. A reader\n  streams records into a bounded channel, N workers process in\n  parallel (typically `NumCPU()`), a collector aggregates results.\n  Channel buffer roughly `2 * N` for smooth flow.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Blocking the event loop with CPU-bound work in async code.** An async function that runs a tight computation loop, calls a synchronous file I\u002FO function, or invokes a C extension that holds the GIL will block the entire event loop — other coroutines cannot run until it returns. Offload CPU-bound or blocking work to a thread pool (`asyncio.to_thread`, `tokio::task::spawn_blocking`) so the event loop stays responsive.\n- **Unbounded channels or queues.** A channel with no capacity limit grows without bound when the producer outpaces the consumer, eventually exhausting memory. Always size queues explicitly and design what happens when the queue is full — block the producer, drop low-priority items, or apply backpressure upstream.\n- **Holding a lock across an await point or blocking I\u002FO call.** Acquiring a mutex and then awaiting a network call while holding it blocks all other waiters for the entire I\u002FO duration and can deadlock if a waiter also tries to acquire the lock. Release the lock before any await; restructure to hold it only for the actual state mutation.\n- **Introducing shared mutable state as the first solution.** Shared state protected by a mutex is correct only if the lock is always acquired, never held too long, and acquired in consistent order. Start from message passing — channels, actors, or immutable data passed between workers — and add shared state only when message passing is genuinely awkward.\n- **Manual lock\u002Funlock instead of scoped guards.** A lock acquired with a manual `lock()` call that is only released in a `finally` block is released incorrectly on early returns, panics, or exceptions that bypass the finally. Use scoped guards (RAII in Rust, `with` in Python, `synchronized` in Java) so the lock is always released when the scope exits.\n- **Using parallelism for I\u002FO-bound tasks and concurrency for CPU-bound tasks.** Spawning 100 OS threads for 100 simultaneous database queries wastes memory and scheduler overhead — a single async event loop handles this with far less overhead. Conversely, running CPU-heavy image processing inside an async event loop starves other coroutines. Match the tool to the bottleneck: async\u002Fcoroutines for I\u002FO, threads\u002Fprocesses for CPU.\n- **No graceful shutdown for worker pools.** A thread or goroutine pool that is not given a shutdown signal when the application exits leaves background workers running indefinitely or drops in-flight work. Use a stop channel, context cancellation, or a sentinel value so all workers drain and exit cleanly on shutdown.\n\n## Full reference\n\n### Pattern catalog\n\n#### Producer-Consumer\n\nOne or more producers generate work items, one or more consumers\nprocess them, connected by a shared queue. Use to decouple data\ngeneration from processing, smooth bursts, or bridge different\nproduction and consumption rates.\n\n```python\nimport queue, threading\n\nq = queue.Queue(maxsize=100)  # bounded for backpressure\n\ndef producer():\n    for item in generate_items():\n        q.put(item)  # blocks when full\n    q.put(None)  # sentinel\n\ndef consumer():\n    while (item := q.get()) is not None:\n        process(item)\n```\n\n#### Reader-Writer\n\nMany readers concurrently or one exclusive writer. Use for read-heavy\nworkloads with infrequent updates (configuration, caches, lookup\ntables). Watch for **writer starvation** — most implementations have\na fair scheduling policy to prevent it.\n\n#### Fork-Join\n\nSplit a task into independent subtasks, run in parallel, combine\nresults. Use for embarrassingly parallel problems (map-reduce,\nparallel sort, image processing).\n\n```go\nfunc processChunks(data []Item) []Result {\n    chunks := split(data, runtime.NumCPU())\n    results := make(chan []Result, len(chunks))\n    for _, chunk := range chunks {\n        go func(c []Item) { results \u003C- processChunk(c) }(chunk)\n    }\n    var combined []Result\n    for range chunks {\n        combined = append(combined, \u003C-results...)\n    }\n    return combined\n}\n```\n\n#### Pipeline\n\nChain of stages connected by channels. Each stage runs concurrently,\nprocessing items as they flow through. Use for multi-step data\ntransformations where each step can be parallelized independently.\n\n#### Barrier\n\nA synchronization point where all threads must arrive before any can\nproceed. Use for phased computation: simulations, iterative\nalgorithms, where every worker must finish phase N before any starts\nphase N+1.\n\n#### Semaphore\n\nLimits concurrent access to a resource or section of code. Use for\nconnection pools, rate limiting, and bounded parallelism.\n\n```python\nimport asyncio\nsem = asyncio.Semaphore(10)  # max 10 concurrent requests\n\nasync def fetch(url):\n    async with sem:\n        return await http_client.get(url)\n```\n\n#### Future \u002F Promise\n\nA placeholder for a value that will be available later. Compose\nasynchronous operations and combine results from multiple concurrent\ntasks. `tokio::join!` in Rust, `Promise.all` in JavaScript.\n\n#### Actor model\n\nIsolated actors communicate exclusively through asynchronous\nmessages. Each actor owns private state and processes one message at\na time from its mailbox. Properties:\n\n- **No shared state** — all communication is via messages\n- **Location transparency** — actors can be local or remote\n- **Fault isolation** — one actor crashing does not affect others\n- **Supervision trees** (Erlang\u002FAkka) — parent actors restart failed\n  children\n\nBest fit: distributed systems, fault-tolerant services, complex state\nmachines with many independent entities (game servers, IoT device\nmanagers).\n\nThe full pattern catalog with extended examples lives in\n`references\u002Fpatterns-catalog.md`.\n\n### Deadlock prevention\n\nCoffman's four conditions: mutual exclusion, hold-and-wait, no\npreemption, circular wait. Break any one to prevent deadlock:\n\n- **Lock ordering** — always acquire locks in a consistent global\n  order.\n- **Try-lock with timeout** — `try_lock()` with a deadline, then back\n  off and retry.\n- **Reduce lock scope** — restructure to avoid holding multiple locks\n  simultaneously.\n- **Lock-free algorithms** — atomics and CAS (compare-and-swap) for\n  simple operations.\n\nDetection in development: Rust `parking_lot` deadlock detection,\nGo `GODEBUG=mutexprofile`, Java `jstack` thread dumps.\n\n### Race condition detection\n\nRace conditions occur when correctness depends on the timing of\nuncontrolled events. Tools:\n\n- **Rust** — compile-time prevention via the ownership system; use\n  `cargo miri` for unsafe code\n- **Go** — `go run -race` \u002F `go test -race` (ThreadSanitizer)\n- **C\u002FC++** — ThreadSanitizer (`-fsanitize=thread`), Helgrind\n- **Java** — FindBugs\u002FSpotBugs, ThreadSanitizer integrations\n\nPatterns that indicate races:\n\n- Check-then-act without holding a lock (TOCTOU)\n- Publishing a partially initialized object\n- Updating a shared collection without synchronization\n- Non-atomic read-modify-write sequences\n\n### Anti-patterns\n\n- **Blocking the event loop** with CPU work in async code — offload\n  to a thread pool (`asyncio.to_thread`, `tokio::task::spawn_blocking`).\n- **Unbounded channels** — always size for backpressure.\n- **Holding a lock across an await or I\u002FO call** — releases other\n  workers from making progress and invites deadlock.\n- **Sharing mutable state by default** — start from message passing\n  and only add shared state when measured.\n- **Manual lock\u002Funlock** instead of scoped guards — leaks on early\n  return or panic.\n\n### Pattern selection guide\n\n| Situation | Pattern |\n|---|---|\n| Decouple fast producer from slow consumer | Producer-Consumer |\n| Many readers, few writers | Reader-Writer |\n| Split work, combine results | Fork-Join |\n| Multi-stage data transformation | Pipeline |\n| Synchronize phases of computation | Barrier |\n| Limit concurrent access to a resource | Semaphore |\n| Compose multiple async operations | Future\u002FPromise |\n| Independent entities with private state | Actor model |\n| Bounded parallel processing of a queue | Thread pool + work queue |\n","# Concurrency Patterns\n\n## Intro\n\nConcurrency is about structuring a program to handle multiple tasks;\nparallelism is about running them on multiple cores simultaneously.\nPick the model that matches the bottleneck (I\u002FO vs CPU), prefer\nmessage passing over shared state, and design for backpressure from\nday one.\n\n## Overview\n\n### Concurrency vs parallelism\n\nConcurrency is a structuring technique — interleaving tasks so the\nprogram makes progress on many things at once, even on a single core.\nParallelism is true simultaneous execution across multiple cores.\nChoose based on the bottleneck:\n\n- **I\u002FO-bound** (network, disk, database): use concurrency\n  (async\u002Fawait or green threads). One thread can multiplex thousands\n  of connections.\n- **CPU-bound** (computation, data processing): use parallelism (OS\n  threads or processes) so all cores are busy.\n- **Mixed**: combine both — async for I\u002FO at the edges, a thread or\n  process pool for the CPU-heavy core.\n\n### Choosing a concurrency model\n\n| Model | Best for | Watch out for |\n|---|---|---|\n| **async\u002Fawait** | High-concurrency I\u002FO (web servers, API clients) | Don't block the event loop with CPU work |\n| **OS threads** | CPU-bound parallelism, simple shared state | Per-thread stack overhead, limited scalability |\n| **Green threads \u002F goroutines** | Massive concurrency with simple code (Go, Erlang) | Scheduler quirks, blocking FFI calls |\n| **Actors** | Distributed systems, fault isolation | Ordering guarantees, debugging |\n| **Channels \u002F message passing** | Decoupled producer-consumer pipelines | Backpressure, channel capacity |\n| **Thread pool + work queue** | Bounded parallelism for batch jobs | Queue sizing, graceful shutdown |\n\n### Managing shared state\n\nPrefer message passing. When shared state is unavoidable, pick the\nright primitive:\n\n- **Mutex** — one writer or one reader at a time. Use for general\n  shared mutable state.\n- **RwLock** — many concurrent readers or one exclusive writer. Use\n  when reads vastly outnumber writes (configuration, lookup tables).\n- **Atomics** — lock-free updates for simple values like counters and\n  flags. Cheapest option when it fits.\n- **Concurrent data structures** — ConcurrentHashMap, DashMap, sync\n  collections — let the library handle synchronization for you.\n\nHold locks for the shortest possible duration. Never perform I\u002FO or\nallocations while holding a lock. Prefer scoped lock guards\n(`Arc\u003CMutex\u003CT>>`, `synchronized` blocks) over manual lock\u002Funlock.\n\n### Backpressure\n\nWhen producers outpace consumers, unbounded queues cause memory\nexhaustion. Design backpressure in from the start:\n\n- **Bounded channels** — block or reject the producer when full.\n- **Rate limiting** — control the inbound rate at the edge.\n- **Load shedding** — drop low-priority work under pressure.\n- **Reactive streams** — propagate demand signals upstream so the\n  producer slows down naturally.\n\n```go\n\u002F\u002F Go: bounded channel provides natural backpressure\njobs := make(chan Job, 100)  \u002F\u002F blocks producer when 100 items queued\n```\n\n### Example workflows\n\n- **I\u002FO-bound web scraper:** async\u002Fawait with a semaphore capping\n  concurrency (e.g. 50 simultaneous requests). `tokio::spawn` plus\n  `tokio::sync::Semaphore` in Rust, or `asyncio.gather` with\n  `asyncio.Semaphore` in Python.\n- **Bulk record processing:** fan-out \u002F fan-in pipeline. A reader\n  streams records into a bounded channel, N workers process in\n  parallel (typically `NumCPU()`), a collector aggregates results.\n  Channel buffer roughly `2 * N` for smooth flow.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Blocking the event loop with CPU-bound work in async code.** An async function that runs a tight computation loop, calls a synchronous file I\u002FO function, or invokes a C extension that holds the GIL will block the entire event loop — other coroutines cannot run until it returns. Offload CPU-bound or blocking work to a thread pool (`asyncio.to_thread`, `tokio::task::spawn_blocking`) so the event loop stays responsive.\n- **Unbounded channels or queues.** A channel with no capacity limit grows without bound when the producer outpaces the consumer, eventually exhausting memory. Always size queues explicitly and design what happens when the queue is full — block the producer, drop low-priority items, or apply backpressure upstream.\n- **Holding a lock across an await point or blocking I\u002FO call.** Acquiring a mutex and then awaiting a network call while holding it blocks all other waiters for the entire I\u002FO duration and can deadlock if a waiter also tries to acquire the lock. Release the lock before any await; restructure to hold it only for the actual state mutation.\n- **Introducing shared mutable state as the first solution.** Shared state protected by a mutex is correct only if the lock is always acquired, never held too long, and acquired in consistent order. Start from message passing — channels, actors, or immutable data passed between workers — and add shared state only when message passing is genuinely awkward.\n- **Manual lock\u002Funlock instead of scoped guards.** A lock acquired with a manual `lock()` call that is only released in a `finally` block is released incorrectly on early returns, panics, or exceptions that bypass the finally. Use scoped guards (RAII in Rust, `with` in Python, `synchronized` in Java) so the lock is always released when the scope exits.\n- **Using parallelism for I\u002FO-bound tasks and concurrency for CPU-bound tasks.** Spawning 100 OS threads for 100 simultaneous database queries wastes memory and scheduler overhead — a single async event loop handles this with far less overhead. Conversely, running CPU-heavy image processing inside an async event loop starves other coroutines. Match the tool to the bottleneck: async\u002Fcoroutines for I\u002FO, threads\u002Fprocesses for CPU.\n- **No graceful shutdown for worker pools.** A thread or goroutine pool that is not given a shutdown signal when the application exits leaves background workers running indefinitely or drops in-flight work. Use a stop channel, context cancellation, or a sentinel value so all workers drain and exit cleanly on shutdown.\n\n## Full reference\n\n### Pattern catalog\n\n#### Producer-Consumer\n\nOne or more producers generate work items, one or more consumers\nprocess them, connected by a shared queue. Use to decouple data\ngeneration from processing, smooth bursts, or bridge different\nproduction and consumption rates.\n\n```python\nimport queue, threading\n\nq = queue.Queue(maxsize=100)  # bounded for backpressure\n\ndef producer():\n    for item in generate_items():\n        q.put(item)  # blocks when full\n    q.put(None)  # sentinel\n\ndef consumer():\n    while (item := q.get()) is not None:\n        process(item)\n```\n\n#### Reader-Writer\n\nMany readers concurrently or one exclusive writer. Use for read-heavy\nworkloads with infrequent updates (configuration, caches, lookup\ntables). Watch for **writer starvation** — most implementations have\na fair scheduling policy to prevent it.\n\n#### Fork-Join\n\nSplit a task into independent subtasks, run in parallel, combine\nresults. Use for embarrassingly parallel problems (map-reduce,\nparallel sort, image processing).\n\n```go\nfunc processChunks(data []Item) []Result {\n    chunks := split(data, runtime.NumCPU())\n    results := make(chan []Result, len(chunks))\n    for _, chunk := range chunks {\n        go func(c []Item) { results \u003C- processChunk(c) }(chunk)\n    }\n    var combined []Result\n    for range chunks {\n        combined = append(combined, \u003C-results...)\n    }\n    return combined\n}\n```\n\n#### Pipeline\n\nChain of stages connected by channels. Each stage runs concurrently,\nprocessing items as they flow through. Use for multi-step data\ntransformations where each step can be parallelized independently.\n\n#### Barrier\n\nA synchronization point where all threads must arrive before any can\nproceed. Use for phased computation: simulations, iterative\nalgorithms, where every worker must finish phase N before any starts\nphase N+1.\n\n#### Semaphore\n\nLimits concurrent access to a resource or section of code. Use for\nconnection pools, rate limiting, and bounded parallelism.\n\n```python\nimport asyncio\nsem = asyncio.Semaphore(10)  # max 10 concurrent requests\n\nasync def fetch(url):\n    async with sem:\n        return await http_client.get(url)\n```\n\n#### Future \u002F Promise\n\nA placeholder for a value that will be available later. Compose\nasynchronous operations and combine results from multiple concurrent\ntasks. `tokio::join!` in Rust, `Promise.all` in JavaScript.\n\n#### Actor model\n\nIsolated actors communicate exclusively through asynchronous\nmessages. Each actor owns private state and processes one message at\na time from its mailbox. Properties:\n\n- **No shared state** — all communication is via messages\n- **Location transparency** — actors can be local or remote\n- **Fault isolation** — one actor crashing does not affect others\n- **Supervision trees** (Erlang\u002FAkka) — parent actors restart failed\n  children\n\nBest fit: distributed systems, fault-tolerant services, complex state\nmachines with many independent entities (game servers, IoT device\nmanagers).\n\nThe full pattern catalog with extended examples lives in\n`references\u002Fpatterns-catalog.md`.\n\n### Deadlock prevention\n\nCoffman's four conditions: mutual exclusion, hold-and-wait, no\npreemption, circular wait. Break any one to prevent deadlock:\n\n- **Lock ordering** — always acquire locks in a consistent global\n  order.\n- **Try-lock with timeout** — `try_lock()` with a deadline, then back\n  off and retry.\n- **Reduce lock scope** — restructure to avoid holding multiple locks\n  simultaneously.\n- **Lock-free algorithms** — atomics and CAS (compare-and-swap) for\n  simple operations.\n\nDetection in development: Rust `parking_lot` deadlock detection,\nGo `GODEBUG=mutexprofile`, Java `jstack` thread dumps.\n\n### Race condition detection\n\nRace conditions occur when correctness depends on the timing of\nuncontrolled events. Tools:\n\n- **Rust** — compile-time prevention via the ownership system; use\n  `cargo miri` for unsafe code\n- **Go** — `go run -race` \u002F `go test -race` (ThreadSanitizer)\n- **C\u002FC++** — ThreadSanitizer (`-fsanitize=thread`), Helgrind\n- **Java** — FindBugs\u002FSpotBugs, ThreadSanitizer integrations\n\nPatterns that indicate races:\n\n- Check-then-act without holding a lock (TOCTOU)\n- Publishing a partially initialized object\n- Updating a shared collection without synchronization\n- Non-atomic read-modify-write sequences\n\n### Anti-patterns\n\n- **Blocking the event loop** with CPU work in async code — offload\n  to a thread pool (`asyncio.to_thread`, `tokio::task::spawn_blocking`).\n- **Unbounded channels** — always size for backpressure.\n- **Holding a lock across an await or I\u002FO call** — releases other\n  workers from making progress and invites deadlock.\n- **Sharing mutable state by default** — start from message passing\n  and only add shared state when measured.\n- **Manual lock\u002Funlock** instead of scoped guards — leaks on early\n  return or panic.\n\n### Pattern selection guide\n\n| Situation | Pattern |\n|---|---|\n| Decouple fast producer from slow consumer | Producer-Consumer |\n| Many readers, few writers | Reader-Writer |\n| Split work, combine results | Fork-Join |\n| Multi-stage data transformation | Pipeline |\n| Synchronize phases of computation | Barrier |\n| Limit concurrent access to a resource | Semaphore |\n| Compose multiple async operations | Future\u002FPromise |\n| Independent entities with private state | Actor model |\n| Bounded parallel processing of a queue | Thread pool + work queue |\n",{"name":5,"metadata":44,"description":50},{"processkit":45},{"id":46,"created":47,"version":48,"category":36,"apiVersion":49},"SKILL-concurrency-patterns",1775433600000,"1.1.0","processkit.projectious.work\u002Fv1","Concurrency and parallelism patterns — async\u002Fawait, threads, actors, channels, deadlock prevention. Use when choosing a concurrency model, designing concurrent or parallel pipelines, debugging deadlocks or race conditions, or reasoning about shared state and backpressure.\n","main","4876a92620ee792aac2ac9a1a806322d8a572367","archive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.18.1\u002Fcontext\u002Fskills\u002Fengineering\u002Fconcurrency-patterns","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit","https:\u002F\u002Fprojectious-work.github.io\u002Fprocesskit\u002F","https:\u002F\u002Fgithub.com\u002Fprojectious-work","2026-11-11 23:24:18",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add projectious-work\u002Fprocesskit --skill concurrency-patterns",{"tool":64,"command":65},"bunx","bunx skills add projectious-work\u002Fprocesskit --skill concurrency-patterns",{"tool":67,"command":68},"pnpm","pnpm dlx skills add projectious-work\u002Fprocesskit --skill concurrency-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.18.1\u002Fcontext\u002Fskills\u002Fengineering\u002Fconcurrency-patterns\u002FSKILL.md",true,[72],{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"references\u002Fpatterns-catalog.md","REFERENCE","参考文档",5796,"https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.18.1\u002Fcontext\u002Fskills\u002Fengineering\u002Fconcurrency-patterns\u002Freferences\u002Fpatterns-catalog.md",[79,105,125,146,163,181],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":90,"publishedAt":39},"01M6X5MTC89B4ZGXW3JVSQCPF8","skill-management","Manage Skill package manifests as v1 ontology entities.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fskill-management\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[91,92,93,94,95,96,32,97,98,99,81,100,101,102,24,103,104],"management","skill management","create","update","package","alpha","list","manage","ontology","get","as","manifests","skill package","transition",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":112,"publishedAt":39},"01M6X5MCV74NHW5MEDNHZRF2C8","schema-management","Manage generated processkit schema contracts through deterministic MCP rebuild and inspection workflows.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fschema-management\u002FSKILL.md",[111],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[91,113,114,115,116,117,96,32,118,119,98,120,121,122,100,123,124],"schema","schema management","MCP","workflows","validation","generated","rebuild","contracts","wed","deterministic","contract","mode",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":39},"01M6X5M5G6YJ96AMZGSCZJ1D13","proposition-management","Record claims, risks, beliefs, world facts, WSJF estimates, and assumptions through the Proposition interface.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fproposition-management\u002FSKILL.md",[],[91,132,133,93,94,134,96,32,135,136,137,138,100,139,140,141,142,143,144,145],"proposition","proposition management","index","log","world","record","query","creation","event","interface","updates","facts","claims","WSJF",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":39},"01M6X5KMQ83QN9M6MPWZM7344F","ontology-management","Manage generated v1 ontology entities that do not require a dedicated domain server.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fontology-management\u002FSKILL.md",[],[91,99,153,93,96,154,155,118,156,135,98,157,158,100,159,160,140,161,24,162],"ontology management","lifecycle","archive","roadmap","do","domain","iteration","keep","measurement","generic",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":169,"publishedAt":39},"01M6X5KCY2DN3SM21RERSFNEBT","okf-compatibility","Import, export, and validate conformant Open Knowledge Format bundles.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fokf-compatibility\u002FSKILL.md",[],[170,171,172,173,96,174,175,176,32,177,178,179,180],"okf","compatibility","okf compatibility","validate","open","knowledge","format","export","bundles","bundle","import",{"skillNo":182,"name":183,"nameZh":6,"description":184,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":185,"categories":186,"keywords":187,"publishedAt":39},"01M6X5JA8S5PNGJVFW4EQY8T83","capability-management","Manage versioned Capability entities and their governed lifecycle.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fcapability-management\u002FSKILL.md",[],[91,188,189,93,94,134,96,154,32,97,135,190,98,137,100,160,140,141,191,104],"capability","capability management","queries","changes"]