rust-concurrency
/rust-concurrency
Dobiera model współbieżności do kształtu zadania: rayon dla danych, wątki z zakresem, kanały do przekazania, a stan współdzielony na końcu.
- Autor
- rewrite-rs ↗
- Repozytorium
- skills ↗
- Licencja
- BSD-3-Clause
- Ostatnia zmiana repozytorium
- 16.08.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 2
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 0
Brak sygnałów. Repozytorium zmienione 16.08.2026, bez odwołań do wycofanych modeli i API.
BSD-3-Clause, otwarta.
Co robi i kiedy
Dobiera model współbieżności do kształtu zadania: rayon dla danych, wątki z zakresem, kanały do przekazania, a stan współdzielony na końcu.
Oryginalny opis (EN)
Pick the concurrency model from the workload shape — rayon for data parallelism, scoped threads for borrowed stack data, channels for handoff, shared state last — and use the weakest correct atomic ordering. Use when writing or reviewing threaded Rust, when Mutex, RwLock, atomics, or manual Send/Sync appear, when a deadlock or data race is suspected, or when the user asks how to parallelize Rust code.
Jak działa
- The shape picks the model
- Data parallelism
- Scoped threads
- Channels for handoff
- Shared state
- Atomics and orderings
- Manual Send/Sync is an unsafe claim
- threadlocal! over static mut
- Deferrals
- Verification
Podgląd SKILL.md
---
name: rust-concurrency
description: Pick the concurrency model from the workload shape — rayon for data parallelism, scoped threads for borrowed stack data, channels for handoff, shared state last — and use the weakest correct atomic ordering. Use when writing or reviewing threaded Rust, when Mutex, RwLock, atomics, or manual Send/Sync appear, when a deadlock or data race is suspected, or when the user asks how to parallelize Rust code.
---
# Rust Concurrency
The shape of the workload picks the model. This skill owns that pick for
threads, and it stops where task concurrency begins — runtime, executors,
`spawn_blocking`, and cancellation live in `/async-rust`.
## The shape picks the model
- The same operation over many independent items: data parallelism, `rayon`.
- Independent units of work that are mostly waiting: task concurrency,
`/async-rust`, not here.
- State several threads read and write: shared state — the one to reach for
last, because it is the only one of the three that can deadlock.
## Data parallelism
`par_iter()` is a one-word change to an iterator chain that already exists —
exactly why the chain was worth writing. The precondition: the per-item work
has to be large enough to pay for the scheduling. A `par_iter` over a million
cheap closures is often slower, and is the standard disappointment.
## Scoped threads
`std::thread::scope` lets a thread borrow stack data, because the scope
guarantees the join before the stack unwinds — which is what removes the
`'static` bound that otherwise forces an `Arc`:
```rust
fn sum_halves(data: &[u64]) -> u64 {
let (left, right) = data.split_at(data.len() / 2);
std::thread::scope(|s| {
let a = s.spawn(|| left.iter().sum::<u64>());
let b = s.spawn(|| right.iter().sum::<u64>());
a.join().unwrap() + b.join().unwrap()
})
}
```
Reach for a scope before an `Arc` or a clone buys the second thread.
## Channels for handoff
A channel moves ownership with the message — no lock to hold, nothing to
poison. Sender-drop is the shutdown signal: `recv` reports disconnection.
Bounded versus unbounded is backpressure: an unbounded channel silently
converts a throughput problem into a memory problem.
## Shared state
`Mutex` is the default; `RwLock` pays off only with genuinely read-heavy
access, and can starve writers. A `Mutex` whose holder panicked hands back
an `Err` — propagate it, or `into_inner()` with a written reason, never a
reflexive `unwrap`. Hold the guard for the shortest possible scope, and
never across a call into code that might lock again.
## Atomics and orderings
The rule: `Relaxed` for a counter nobody synchronises on, `Acquire`/`Release`
for a paired handoff where one thread publishes and another observes,
`SeqCst` when unsure and the cost is acceptable. The pair is the one that is
wrong most often:
```rust
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Arc;
fn main() {
let value = Arc::new(AtomicU64::new(0));
let ready = Arc::new(AtomicBool::new(false));
let (v, r) = (Arc::clone(&value), Arc::clone(&ready));
let publisher = std::thread::spawn(move || {
v.store(42, Ordering::Relaxed);
r.store(true, Ordering::Release);
});
while !ready.load(Ordering::Acquire) {
std::thread::yield_now();
}
assert_eq!(value.load(Ordering::Relaxed), 42);
publisher.join().unwrap();
}
```
The `Release` store orders the write to `value` before `ready` flips, and
the `Acquire` load pairs with it. If the ordering argument cannot be
written down in two sentences, the code wants a `Mutex`.
## Manual `Send`/`Sync` is an unsafe claim
`unsafe impl Send for T` asserts what the compiler could not prove; the
`// SAFETY:` comment must hold an actual argument. The soundness review
goes to `/unsafe-rust` — this skill only insists the claim is written.
## `thread_local!` over `static mut`
`static mut` is effectively unusable in current editions and was never
sound to share; `thread_local!` is the per-thread answer. Passing state
beats hiding it in a global — a global is a lifetime nobody wrote down.
## Deferrals
Task concurrency, executors, `spawn_blocking`, and cancellation are
`/async-rust`. Whether the state should be shared at all is
`/ownership-not-clone`. The soundness of an `unsafe impl` is `/unsafe-rust`.
Throughput of the parallel version is `/rust-performance`.
## Verification
```bash
cargo test # including the ignored-by-default stress tests, if the repo has any
cargo clippy --all-targets # at the level the repo configures
cargo miri test # where atomics or unsafe Send/Sync are involved
```
Clippy runs at the lint level the target repo configures; `-D warnings`
is the fallback only when the repo configures no lints at all. Lock-free
structures and non-trivial ordering arguments want `loom` — it explores
interleavings exhaustively rather than hoping the scheduler picks the
bad one; it runs under its own cfg, and the model has to be small.
Pliki w paczce (2)
- SKILL.md 5 KB
- agents/openai.yaml 1 KB
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · rewrite-rs/skills | 100 | BSD-3-Clause |
| full-stack-skills/rust-skills | 100 | Apache-2.0 |
| heyAyushh/stacc | 95 | MIT |
| heyAyushh/stacc | 95 | MIT |
Migawka bazy z 28.10.2026 · wersja paczki 1d1cb42cfa3f (skrót SHA-256 całej paczki)
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100rust
Podaje zasady Rust dla workspace Carbon: Tokio przy obciążeniach CPU i FFI C++, dobór Mutex, RwLock i rayon oraz szukanie alokacji na podstawie pomiarów. - 95rust-performance
Optymalizuje wydajność kodu Rust: profilowanie, benchmarki, mniej alokacji, lokalność cache, rayon i SIMD. - 90concurrency-and-parallelism
Pomaga pisać i sprawdzać kod współbieżny: wątki, async, blokady, diagnozowanie wyścigów oraz zakleszczeń. - 100memory-model
Wyjaśnia model pamięci C++ i Rust dla programowania współbieżnego: kolejność dostępu, acquire-release, seq_cst, happens-before, wyścigi danych i struktury lock-free. - 100rust
Pomaga w konwencjach, idiomach i obsłudze błędów w Rust: współbieżność z wątkami i Tokio, cargo, clippy, rustfmt i rustdoc. - 95async-rust
Pisze i sprawdza poprawny asynchroniczny kod w Rust: wybór runtime, granice Send i Sync, anulowanie, zadania blokujące i stan współdzielony.