/m07-concurrency
CRITICAL: Use for concurrency/async. Triggers: E0277 Send Sync, cannot be sent between threads, thread, spawn, channel, mpsc, Mutex, RwLock, Atomic, async, await, Future, tokio, deadlock, race condition, 并发, 线程, 异步, 死锁
$ npx -y skills add zhanghandong/rust-skills --skill m07-concurrency --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/m07-concurrency
Context preview
The summary Claude sees to decide when to auto-load this skill.
CRITICAL: Use for concurrency/async. Triggers: E0277 Send Sync, cannot be sent between threads, thread, spawn, channel, mpsc, Mutex, RwLock, Atomic, async, await, Future, tokio, deadlock, race condition, 并发, 线程, 异步, 死锁
SKILL.md
m07-concurrency.SKILL.mdname: m07-concurrency
description: "CRITICAL: Use for concurrency/async. Triggers: E0277 Send Sync, cannot be sent between threads, thread, spawn, channel, mpsc, Mutex, RwLock, Atomic, async, await, Future, tokio, deadlock, race condition, 并发, 线程, 异步, 死锁"
user-invocable: false
Concurrency
> **Layer 1: Language Mechanics**
Core Question
**Is this CPU-bound or I/O-bound, and what's the sharing model?**
Before choosing concurrency primitives:
- What's the workload type?
- What data needs to be shared?
- What's the thread safety requirement?
---
Error → Design Question
| Error | Don't Just Say | Ask Instead | |-------|----------------|-------------| | E0277 Send | "Add Send bound" | Should this type cross threads? | | E0277 Sync | "Wrap in Mutex" | Is shared access really needed? | | Future not Send | "Use spawn_local" | Is async the right choice? | | Deadlock | "Reorder locks" | Is the locking design correct? |
---
Thinking Prompt
Before adding concurrency:
1. **What's the workload?**
- CPU-bound → threads (std::thread, rayon)
- I/O-bound → async (tokio, async-std)
- Mixed → hybrid approach
2. **What's the sharing model?**
- No sharing → message passing (channels)
- Immutable sharing → Arc<T>
- Mutable sharing → Arc<Mutex<T>> or Arc<RwLock<T>>
3. **What are the Send/Sync requirements?**
- Cross-thread ownership → Send
- Cross-thread references → Sync
- Single-thread async → spawn_local
---
Trace Up ↑ (MANDATORY)
**CRITICAL**: Don't just fix the error. Trace UP to find domain constraints.
Domain Detection Table
| Context Keywords | Load Domain Skill | Key Constraint | |-----------------|-------------------|----------------| | Web API, HTTP, axum, actix, handler | **domain-web** | Handlers run on any thread | | 交易, 支付, trading, payment | **domain-fintech** | Audit + thread safety | | gRPC, kubernetes, microservice | **domain-cloud-native** | Distributed tracing | | CLI, terminal, clap | **domain-cli** | Usually single-thread OK |
Example: Web API + Rc Error
"Rc cannot be sent between threads" in Web API context
↑ DETECT: "Web API" → Load domain-web
↑ FIND: domain-web says "Shared state must be thread-safe"
↑ FIND: domain-web says "Rc in state" is Common Mistake
↓ DESIGN: Use Arc<T> with State extractor
↓ IMPL: axum::extract::State<Arc<AppConfig>>Generic Trace
"Send not satisfied for my type"
↑ Ask: What domain is this? Load domain-* skill
↑ Ask: Does this type need to cross thread boundaries?
↑ Check: m09-domain (is the data model correct?)| Situation | Trace To | Question | |-----------|----------|----------| | Send/Sync in Web | **domain-web** | What's the state management pattern? | | Send/Sync in CLI | **domain-cli** | Is multi-thread really needed? | | Mutex vs channels | m09-domain | Shared state or message passing? | | Async vs threads | m10-performance | What's the workload profile? |
---
Trace Down ↓
From design to implementation:
"Need parallelism for CPU work"
↓ Use: std::thread or rayon
"Need concurrency for I/O"
↓ Use: async/await with tokio
"Need to share immutable data across threads"
↓ Use: Arc<T>
"Need to share mutable data across threads"
↓ Use: Arc<Mutex<T>> or Arc<RwLock<T>>
↓ Or: channels for message passing
"Need simple atomic operations"
↓ Use: AtomicBool, AtomicUsize, etc.---
Send/Sync Markers
| Marker | Meaning | Example | |--------|---------|---------| | `Send` | Can transfer ownership between threads | Most types | | `Sync` | Can share references between threads | `Arc<T>` | | `!Send` | Must stay on one thread | `Rc<T>` | | `!Sync` | No shared refs across threads | `RefCell<T>` |
Quick Reference
| Pattern | Thread-Safe | Blocking | Use When | |---------|-------------|----------|----------| | `std::thread` | Yes | Yes | CPU-bound parallelism | | `async/await` | Yes | No | I/O-bound concurrency | | `Mutex<T>` | Yes | Yes | Shared mutable state | | `RwLock<T>` | Yes | Yes | Read-heavy shared state | | `mpsc::channel` | Yes | Optional | Message passing | | `Arc<Mutex<T>>` | Yes | Yes | Shared mutable across threads |
Decision Flowchart
What type of work?
├─ CPU-bound → std::thread or rayon
├─ I/O-bound → async/await
└─ Mixed → hybrid (spawn_blocking)
Need to share data?
├─ No → message passing (channels)
├─ Immutable → Arc<T>
└─ Mutable →
├─ Read-heavy → Arc<RwLock<T>>
└─ Write-heavy → Arc<Mutex<T>>
└─ Simple counter → AtomicUsize
Async context?
├─ Type is Send → tokio::spawn
├─ Type is !Send → spawn_local
└─ Blocking code → spawn_blocking
---
Common Errors
| Error | Cause | Fix | |-------|-------|-----| | E0277 `Send` not satisfied | Non-Send in async | Use Arc or spawn_local | | E0277 `Sync` not satisfied | Non-Sync shared | Wrap with Mutex | | Deadlock | Lock ordering | Consistent lock order | | `future is not Send` | Non-Send across await | Drop before await | | `MutexGuard` across await | Guard held during suspend | Scope guard properly |
---
Anti-Patterns
| Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | Arc<Mutex<T>> everywhere | Contention, complexity | Message passing | | thread::sleep in async | Blocks executor | tokio::time::sleep | | Holding locks across await | Blocks other tasks | Scope locks tightly | | Ignoring deadlock risk | Hard to debug | Lock ordering, try_lock |
---
Async-Specific Patterns
Avoid MutexGuard Across Await
// Bad: guard held across await
let guard = mutex.lock().await;
do_async().await; // guard still held!
// Good: scope the lock
{
let guard = mutex.lock().await;
// use guard
} // guard dropped
do_async().await;Non-Send Types in Async
// Rc is !Send, can't cross await in spawned task
// Option 1: use Arc instead
// Option 2: use spawn_local (single-thread runtime)
// Option 3: ensure Rc is dropped before .await
---
Related Skills
|
Read more
name: m07-concurrency description: "CRITICAL: Use for concurrency/async. Triggers: E0277 Send Sync, cannot be sent between threads, thread, spawn, channel, mpsc, Mutex, RwLock, Atomic, async, await, Future, tokio, deadlock, race condition, 并发, 线程, 异步, 死锁" user-invocable: false
Concurrency
> **Layer 1: Language Mechanics**
Core Question
**Is this CPU-bound or I/O-bound, and what's the sharing model?**
Before choosing concurrency primitives:
- What's the workload type?
- What data needs to be shared?
- What's the thread safety requirement?
---
Error → Design Question
| Error | Don't Just Say | Ask Instead | |-------|----------------|-------------| | E0277 Send | "Add Send bound" | Should this type cross threads? | | E0277 Sync | "Wrap in Mutex" | Is shared access really needed? | | Future not Send | "Use spawn_local" | Is async the right choice? | | Deadlock | "Reorder locks" | Is the locking design correct? |
---
Thinking Prompt
Before adding concurrency:
1. **What's the workload?**
- CPU-bound → threads (std::thread, rayon)
- I/O-bound → async (tokio, async-std)
- Mixed → hybrid approach
2. **What's the sharing model?**
- No sharing → message passing (channels)
- Immutable sharing → Arc<T>
- Mutable sharing → Arc<Mutex<T>> or Arc<RwLock<T>>
3. **What are the Send/Sync requirements?**
- Cross-thread ownership → Send
- Cross-thread references → Sync
- Single-thread async → spawn_local
---
Trace Up ↑ (MANDATORY)
**CRITICAL**: Don't just fix the error. Trace UP to find domain constraints.
Domain Detection Table
| Context Keywords | Load Domain Skill | Key Constraint | |-----------------|-------------------|----------------| | Web API, HTTP, axum, actix, handler | **domain-web** | Handlers run on any thread | | 交易, 支付, trading, payment | **domain-fintech** | Audit + thread safety | | gRPC, kubernetes, microservice | **domain-cloud-native** | Distributed tracing | | CLI, terminal, clap | **domain-cli** | Usually single-thread OK |
Example: Web API + Rc Error
"Rc cannot be sent between threads" in Web API context
↑ DETECT: "Web API" → Load domain-web
↑ FIND: domain-web says "Shared state must be thread-safe"
↑ FIND: domain-web says "Rc in state" is Common Mistake
↓ DESIGN: Use Arc<T> with State extractor
↓ IMPL: axum::extract::State<Arc<AppConfig>>Generic Trace
"Send not satisfied for my type"
↑ Ask: What domain is this? Load domain-* skill
↑ Ask: Does this type need to cross thread boundaries?
↑ Check: m09-domain (is the data model correct?)| Situation | Trace To | Question | |-----------|----------|----------| | Send/Sync in Web | **domain-web** | What's the state management pattern? | | Send/Sync in CLI | **domain-cli** | Is multi-thread really needed? | | Mutex vs channels | m09-domain | Shared state or message passing? | | Async vs threads | m10-performance | What's the workload profile? |
---
Trace Down ↓
From design to implementation:
"Need parallelism for CPU work"
↓ Use: std::thread or rayon
"Need concurrency for I/O"
↓ Use: async/await with tokio
"Need to share immutable data across threads"
↓ Use: Arc<T>
"Need to share mutable data across threads"
↓ Use: Arc<Mutex<T>> or Arc<RwLock<T>>
↓ Or: channels for message passing
"Need simple atomic operations"
↓ Use: AtomicBool, AtomicUsize, etc.---
Send/Sync Markers
| Marker | Meaning | Example | |--------|---------|---------| | `Send` | Can transfer ownership between threads | Most types | | `Sync` | Can share references between threads | `Arc<T>` | | `!Send` | Must stay on one thread | `Rc<T>` | | `!Sync` | No shared refs across threads | `RefCell<T>` |
Quick Reference
| Pattern | Thread-Safe | Blocking | Use When | |---------|-------------|----------|----------| | `std::thread` | Yes | Yes | CPU-bound parallelism | | `async/await` | Yes | No | I/O-bound concurrency | | `Mutex<T>` | Yes | Yes | Shared mutable state | | `RwLock<T>` | Yes | Yes | Read-heavy shared state | | `mpsc::channel` | Yes | Optional | Message passing | | `Arc<Mutex<T>>` | Yes | Yes | Shared mutable across threads |
Decision Flowchart
What type of work? ├─ CPU-bound → std::thread or rayon ├─ I/O-bound → async/await └─ Mixed → hybrid (spawn_blocking) Need to share data? ├─ No → message passing (channels) ├─ Immutable → Arc<T> └─ Mutable → ├─ Read-heavy → Arc<RwLock<T>> └─ Write-heavy → Arc<Mutex<T>> └─ Simple counter → AtomicUsize Async context? ├─ Type is Send → tokio::spawn ├─ Type is !Send → spawn_local └─ Blocking code → spawn_blocking
---
Common Errors
| Error | Cause | Fix | |-------|-------|-----| | E0277 `Send` not satisfied | Non-Send in async | Use Arc or spawn_local | | E0277 `Sync` not satisfied | Non-Sync shared | Wrap with Mutex | | Deadlock | Lock ordering | Consistent lock order | | `future is not Send` | Non-Send across await | Drop before await | | `MutexGuard` across await | Guard held during suspend | Scope guard properly |
---
Anti-Patterns
| Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | Arc<Mutex<T>> everywhere | Contention, complexity | Message passing | | thread::sleep in async | Blocks executor | tokio::time::sleep | | Holding locks across await | Blocks other tasks | Scope locks tightly | | Ignoring deadlock risk | Hard to debug | Lock ordering, try_lock |
---
Async-Specific Patterns
Avoid MutexGuard Across Await
// Bad: guard held across await
let guard = mutex.lock().await;
do_async().await; // guard still held!
// Good: scope the lock
{
let guard = mutex.lock().await;
// use guard
} // guard dropped
do_async().await;Non-Send Types in Async
// Rc is !Send, can't cross await in spawned task // Option 1: use Arc instead // Option 2: use spawn_local (single-thread runtime) // Option 3: ensure Rc is dropped before .await
---
Related Skills
|
AI-powered Rust development assistant with meta-cognition framework
Other skills on rust-skills.
- /coding-guidelines
Use when asking about Rust code style or best practices. Keywords: naming, formatting, comment, clippy, rustfmt, lint, code style, best practice, P.NAM, G.FMT, code review, naming convention, variable naming, function naming, type naming, 命名规范, 代码风格, 格式化, 最佳实践, 代码审查, 怎么命名
Open skill - /core-actionbook
Internal support skill for actionbook MCP selectors used by Rust documentation research workflows. Use only when another rust-skills workflow explicitly requests actionbook-backed selectors.
Open skill - /core-agent-browser
Internal support skill for agent-browser CLI workflows used by rust-learner, docs-researcher, and crate-researcher. Use only when browser automation is explicitly required.
Open skill - /core-dynamic-skills
Internal command support for dynamic Rust crate skill management. Use only when explicitly invoked by /sync-crate-skills, /clean-crate-skills, or /update-crate-skill.
Open skill - /core-fix-skill-docs
Internal maintenance support for checking and fixing generated Rust skill documentation references. Use only when explicitly invoked by /fix-skill-docs.
Open skill - /domain-cli
Use when building CLI tools. Keywords: CLI, command line, terminal, clap, structopt, argument parsing, subcommand, interactive, TUI, ratatui, crossterm, indicatif, progress bar, colored output, shell completion, config file, environment variable, 命令行, 终端应用, 参数解析
Open skill

