其他
Rust 并发/异步选型与错误修复:根据 CPU/IO…
在 Rust 中处理并发、异步、Send/Sync 编译错误、死锁或竞态时,用于选择正确并发原语并追溯领域约束。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
Rust 并发/异步选型与错误修复:根据通用
解决思路
- 先判断核心问题:当前任务是 CPU-bound 还是 I/O-bound,以及数据共享模型是什么;在选并发原语前回答负载类型、需要共享的数据、线程安全要求。
- 遇到 E0277 Send 时,不要只说「加 Send bound」,而要问:这个类型是否真的需要跨线程?
- 遇到 E0277 Sync 时,不要只说「包 Mutex」,而要问:是否真的需要共享访问?
- 遇到 Future not Send 时,不要只说「用 spawn_local」,而要问:异步是否是正确的选择?
- 遇到 Deadlock 时,不要只说「重排锁顺序」,而要问:锁的设计是否正确?
- 添加并发前判断 workload:CPU-bound 用线程(std::thread、rayon);I/O-bound 用异步(tokio、async-std);混合负载用 hybrid approach。
- 添加并发前判断 sharing model:不共享用消息传递(channels);不可变共享用 Arc<T>;可变共享用 Arc<Mutex<T>> 或 Arc<RwLock<T>>。
- 添加并发前判断 Send/Sync 要求:跨线程所有权用 Send;跨线程引用用 Sync;单线程异步用 spawn_local。
- 必须 Trace Up:不要只修错误,要向上追溯领域约束。
- 按领域检测表处理:出现 Web API、HTTP、axum、actix、handler 时加载 domain-web,并记住 handlers 可运行在任意线程。
- 出现 交易、支付、trading、payment 时加载 domain-fintech,并满足审计 + 线程安全约束。
- 出现 gRPC、kubernetes、microservice 时加载 domain-cloud-native,并考虑分布式追踪。
- 出现 CLI、terminal、clap 时加载 domain-cli,并记住通常单线程即可。
- 对 Web API + Rc 错误按示例处理:检测到 Web API 后加载 domain-web;确认共享状态必须线程安全;识别 Rc in state 是 Common Mistake;设计为 Arc<T> 配合 State extractor;实现为 axum::extract::State<Arc<AppConfig>>。
- 对泛型 Send 不满足问题:先问这是什么领域并加载 domain-* skill;再问该类型是否需要跨线程边界;再检查 m09-domain(数据模型是否正确)。
- 按 Trace To 表追溯:Web 中 Send/Sync 问题查 domain-web 并问状态管理模式是什么。
- CLI 中 Send/Sync 问题查 domain-cli 并问是否真的需要多线程。
- Mutex vs channels 问题查 m09-domain 并问是共享状态还是消息传递。
- Async vs threads 问题查 m10-performance 并问 workload profile 是什么。
- 从设计到实现按 Trace Down 执行:需要 CPU 并行时用 std::thread 或 rayon。
- 需要 I/O 并发时用 async/await 配合 tokio。
- 需要跨线程共享不可变数据时用 Arc<T>。
- 需要跨线程共享可变数据时用 Arc<Mutex<T>> 或 Arc<RwLock<T>>,或用 channels 做消息传递。
- 需要简单原子操作时用 AtomicBool、AtomicUsize 等。
- 判断 Send/Sync 标记:Send 表示可在不同线程间转移所有权,示例为大多数类型;Sync 表示可在不同线程间共享引用,示例为 Arc<T>;!Send 表示必须留在单线程,示例为 Rc<T>;!Sync 表示不能跨线程共享引用,示例为 RefCell<T>。
- 按 Quick Reference 选择模式:std::thread 线程安全且阻塞,适合 CPU-bound parallelism。
- 按 Quick Reference 选择模式:async/await 线程安全且非阻塞,适合 I/O-bound concurrency。
- 按 Quick Reference 选择模式:Mutex<T> 线程安全且阻塞,适合共享可变状态。
- 按 Quick Reference 选择模式:RwLock<T> 线程安全且阻塞,适合读多共享状态。
- 按 Quick Reference 选择模式:mpsc::channel 线程安全、阻塞可选,适合消息传递。
- 按 Quick Reference 选择模式:Arc<Mutex<T>> 线程安全且阻塞,适合跨线程共享可变状态。
- 按决策流程图判断工作类型:CPU-bound 用 std::thread 或 rayon;I/O-bound 用 async/await;Mixed 用 hybrid(spawn_blocking)。
- 按决策流程图判断是否需要共享数据:不需要共享用消息传递(channels);不可变共享用 Arc<T>;可变共享中读多用 Arc<RwLock<T>>;写多用 Arc<Mutex<T>>;简单计数器用 AtomicUsize。
- 按决策流程图判断异步上下文:类型是 Send 用 tokio::spawn;类型是 !Send 用 spawn_local;阻塞代码用 spawn_blocking。
- 修复 E0277 Send not satisfied:原因是 async 中存在非 Send 类型;修复用 Arc 或 spawn_local。
- 修复 E0277 Sync not satisfied:原因是共享了非 Sync 类型;修复用 Mutex 包装。
- 修复 Deadlock:原因是锁顺序;修复为一致的锁顺序。
- 修复 future is not Send:原因是 await 跨过了非 Send 值;修复为在 await 前 drop。
- 修复 MutexGuard across await:原因是 suspend 期间持有 guard;修复为正确限定 guard 作用域。
- 避免反模式 Arc<Mutex<T>> everywhere:它会带来 contention、complexity;改用 message passing。
- 避免反模式 thread::sleep in async:它会阻塞 executor;改用 tokio::time::sleep。
- 避免反模式 Holding locks across await:它会阻塞其他任务;改为 tightly scope locks。
- 避免反模式 Ignoring deadlock risk:它难调试;使用 lock ordering、try_lock。
- 异步特定模式——避免 MutexGuard Across Await:Bad 是在 await 期间持有 guard;Good 是用块作用域锁定,使 guard 在 await 前释放,例如 { let guard = mutex.lock().await; ... } do_async().await;
- 异步特定模式——处理 Non-Send Types in Async:Rc 是 !Send,不能跨 await 进入 spawned task;Option 1 改用 Arc;Option 2 用 spawn_local(单线程 runtime);Option 3 确保 Rc 在 .await 前 drop。
- 相关技能查阅:智能指针选择查 m02-resource;内部可变性查 m03-mutability;性能调优查 m10-performance;领域并发需求查 domain-*。
适用边界 · 注意事项
- 非 Rust 项目或不需要 Rust 并发/异步时不要套用。
- 单线程 CLI、无共享状态或未确认跨线程需求时,不要强行引入线程、async 或 Arc<Mutex<T>>。
- 仅靠调整锁顺序、加 Send bound 或包 Mutex 就能解决表面错误时,不要跳过对数据模型和领域约束的追溯。