{"id":13501007,"url":"https://github.com/quambene/rust-concurrency","last_synced_at":"2025-06-27T23:35:16.367Z","repository":{"id":54606529,"uuid":"497147714","full_name":"quambene/rust-concurrency","owner":"quambene","description":"Rust Concurrency Cheat Sheet","archived":false,"fork":false,"pushed_at":"2024-10-24T22:54:46.000Z","size":31,"stargazers_count":390,"open_issues_count":0,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-02-01T14:26:55.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quambene.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-27T21:53:22.000Z","updated_at":"2024-12-30T22:27:00.000Z","dependencies_parsed_at":"2023-01-29T17:45:16.081Z","dependency_job_id":null,"html_url":"https://github.com/quambene/rust-concurrency","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quambene%2Frust-concurrency","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quambene%2Frust-concurrency/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quambene%2Frust-concurrency/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quambene%2Frust-concurrency/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quambene","download_url":"https://codeload.github.com/quambene/rust-concurrency/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245819868,"owners_count":20677726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:01:22.439Z","updated_at":"2025-03-27T09:40:53.574Z","avatar_url":"https://github.com/quambene.png","language":null,"funding_links":[],"categories":["Others"],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD033 --\u003e\n\n# Rust Concurrency Cheat Sheet\n\n- [Safety](#safety)\n- [Overview](#overview)\n- [Futures](#futures)\n- [Tasks and threads](#tasks-and-threads)\n- [Streams](#streams)\n- [Share state](#share-state)\n- [Marker traits](#marker-traits)\n- [Concurrency models](#concurrency-models)\n- [Terminology](#terminology)\n- [References](#references)\n\n## Safety\n\nRust ensures data race safety through the type system (`Send` and `Sync` marker traits) as well as the ownership and borrowing rules: it is not allowed to alias a mutable reference, so it is not possible to perform a data race.\n\n## Overview\n\n\u0026nbsp; | Problem\n------- | -------\nParallelism | Multi-core utilization\nConcurrency | Single-core idleness\n\n\u0026nbsp; | Solution | Primitive | Type | Description | Examples\n------- | ------- | ------- | ------- | ------- | -------\nParallelism | Multithreading | Thread | `T: Send` | Do work simultaneously on different threads | [`std::thread::spawn`](https://doc.rust-lang.org/std/thread/fn.spawn.html)\nConcurrency | Single-threaded concurrency | Future | `Future` | Futures run concurrently on the same thread | [`futures::future::join`](https://docs.rs/futures/latest/futures/future/fn.join.html), [`futures::join`](https://docs.rs/futures/latest/futures/macro.join.html), [`tokio::join`](https://docs.rs/tokio/latest/tokio/macro.join.html)\nConcurrency\u003cbr\u003e+Parallelism | Multithreaded concurrency | Task | `T: Future + Send` | Tasks run concurrently to other tasks; the task may run on the current thread, or it may be sent to a different thread | [`async_std::task::spawn`](https://docs.rs/async-std/latest/async_std/task/fn.spawn.html), [`tokio::task::spawn`](https://docs.rs/tokio/latest/tokio/fn.spawn.html)\n\n## Futures\n\n``` rust\npub trait Future {\n    type Output;\n    fn poll(self: Pin\u003c\u0026mut Self\u003e, cx: \u0026mut Context\u003c'_\u003e) -\u003e Poll\u003cSelf::Output\u003e;\n}\n\npub enum Poll\u003cT\u003e {\n    Ready(T),\n    Pending,\n}\n```\n\n- `Future` has to be `poll`ed (by the *executor*) to resume where it last yielded and make progress (async is *lazy*)\n- `\u0026mut Self` contains state (state machine)\n- `Pin` the memory location because the future contains self-referential data\n- `Context` contains the `Waker` to notify the executor that progress can be made\n- async/await on futures is implemented by *generators*\n- `async fn` and `async` blocks return `impl Future\u003cOutput = T\u003e`\n- calling `.await` attempts to resolve the `Future`: if the `Future` is blocked, it yields control; if progress can be made, the `Future` resumes\n\nFutures form a tree of futures. The leaf futures commmunicate with the executor. The root future of a tree is called a *task*.\n\n## Tasks and threads\n\nComputation | Examples\n------- | -------\nLightweight (e.g. \u003c100 ms) | [`async_std::task::spawn`](https://docs.rs/async-std/latest/async_std/task/fn.spawn.html), [`tokio::task::spawn`](https://docs.rs/tokio/latest/tokio/task/fn.spawn.html)\nExtensive (e.g. \u003e100 ms or I/O bound) | [`async_std::task::spawn_blocking`](https://docs.rs/async-std/latest/async_std/task/fn.spawn_blocking.html), [`tokio::task::spawn_blocking`](https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html)\nMassive (e.g. running forever or CPU-bound) | [`std::thread::spawn`](https://doc.rust-lang.org/std/thread/fn.spawn.html)\n\n## Streams\n\n``` rust\npub trait Stream {\n    type Item;\n    fn poll_next(self: Pin\u003c\u0026mut Self\u003e, cx: \u0026mut Context\u003c'_\u003e) -\u003e Poll\u003cOption\u003cSelf::Item\u003e\u003e;\n\n    fn size_hint(\u0026self) -\u003e (usize, Option\u003cusize\u003e) { ... }\n}\n```\n\n- [`Stream\u003cItem = T\u003e`](https://docs.rs/futures/latest/futures/stream/trait.Stream.html) is an asynchronous version of [`Iterator\u003cItem = T\u003e`](https://doc.rust-lang.org/std/iter/trait.Iterator.html), i.e., it does not block between each item yield\n\n\u0026nbsp; | Parallelism\n------- | -------\nIterator | [rayon](https://crates.io/crates/rayon)\nStream | [tokio](https://crates.io/crates/tokio), [parallel-stream](https://crates.io/crates/parallel-stream)\n\nOperation | Relationship | Examples\n------- | ------- | -------\nCreate | | [`futures::stream::iter`](https://docs.rs/futures/latest/futures/stream/fn.iter.html), [`futures::stream::once`](https://docs.rs/futures/latest/futures/stream/fn.once.html), [`futures::stream::repeat`](https://docs.rs/futures/latest/futures/stream/fn.repeat.html), [`futures::stream::repeat_with`](https://docs.rs/futures/latest/futures/stream/fn.repeat_with.html), [`async_stream::stream`](https://docs.rs/async-stream/latest/async_stream/macro.stream.html)\nCreate (via channels) | | [`futures::channel::mpsc::Receiver`](https://docs.rs/futures/latest/futures/channel/mpsc/struct.Receiver.html), [`tokio_stream::wrappers::ReceiverStream`](https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.ReceiverStream.html)\nIterate | | [`futures::stream::StreamExt::next`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.next), [`futures::stream::StreamExt::for_each`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.for_each), [`futures::stream::StreamExt::for_each_concurrent`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.for_each_concurrent)\nTransform | 1-1 | [`futures::stream::StreamExt::map`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.map), [`futures::stream::StreamExt::then`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.then), [`futures::stream::StreamExt::flatten`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.flatten)\nFilter | 1-1 | [`futures::stream::StreamExt::filter`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.filter), [`futures::stream::StreamExt::take`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.take), [`futures::stream::StreamExt::skip`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.skip)\nBuffer | 1-1 | [`futures::stream::StreamExt::buffered`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.buffered), [`futures::stream::StreamExt::buffer_unordered`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.buffer_unordered)\nCombine | n-1 | [`futures::stream::StreamExt::chain`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.chain), [`futures::stream::StreamExt::zip`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.zip), [`tokio_stream::StreamExt::merge`](https://docs.rs/tokio-stream/0.1.9/tokio_stream/trait.StreamExt.html#method.merge), [`tokio_stream::StreamMap`](https://docs.rs/tokio-stream/latest/tokio_stream/struct.StreamMap.html), [`tokio::select`](https://docs.rs/tokio/latest/tokio/macro.select.html)\nSplit | 1-n | [`futures::channel::oneshot::Sender::send`](https://docs.rs/futures/latest/futures/channel/oneshot/struct.Sender.html#method.send), [`async_std::channel::Sender::send`](https://docs.rs/async-std/latest/async_std/channel/struct.Sender.html#method.send)\n\n## Share state\n\n\u0026nbsp; | Threads | Tasks\n------- | ------- | -------\nchannel | [`std::sync::mpsc`](https://doc.rust-lang.org/std/sync/mpsc/) (`Send`), [`crossbeam::channel`](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) (`Send`, `Sync`) | [`futures::channel::oneshot`](https://docs.rs/futures/latest/futures/channel/oneshot/index.html), [`tokio::sync::mpsc`](https://docs.rs/tokio/latest/tokio/sync/mpsc/index.html), [`tokio::sync::oneshot`](https://docs.rs/tokio/latest/tokio/sync/oneshot/index.html), [`tokio::sync::broadcast`](https://docs.rs/tokio/latest/tokio/sync/broadcast/index.html), [`tokio::sync::watch`](https://docs.rs/tokio/latest/tokio/sync/watch/index.html), [`async_channel::unbounded`](https://docs.rs/async-channel/latest/async_channel/fn.unbounded.html), [`async_channel::bounded`](https://docs.rs/async-channel/latest/async_channel/fn.bounded.html), [`oneshot`](https://docs.rs/oneshot/latest/oneshot)\nmutex | [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html), [`parking_lot::Mutex`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html) | [`tokio::sync::Mutex`](https://docs.rs/tokio/latest/tokio/sync/struct.Mutex.html)\n\n## Marker traits\n\n- [`Send`](https://doc.rust-lang.org/std/marker/trait.Send.html): safe to send it to another thread\n- [`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html): safe to share between threads (`T` is `Sync` if and only if `\u0026T` is `Send`)\n\nType | `Send` | `Sync` | Owners | Interior mutability\n------- | ------- | ------- | ------- | -------\n[`Rc\u003cT\u003e`](https://doc.rust-lang.org/std/rc/struct.Rc.html) | No | No | multiple | No\n[`Arc\u003cT\u003e`](https://doc.rust-lang.org/std/sync/struct.Arc.html) | Yes (if `T` is `Send` and `Sync`) | Yes (if `T` is `Send` and `Sync`) | multiple | No\n[`Box\u003cT\u003e`](https://doc.rust-lang.org/std/boxed/struct.Box.html) | Yes (if `T` is `Send`) | Yes (if `T` is `Sync`) | single | No\n[`Mutex\u003cT\u003e`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) | Yes (if `T` is `Send`) | Yes (if `T` is `Send`) | single | Yes\n[`RwLock\u003cT\u003e`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) | Yes (if `T` is `Send`) | Yes (if `T` is `Send` and `Sync`) | single | Yes\n[`MutexGuard\u003c'a, T: 'a\u003e`](https://doc.rust-lang.org/std/sync/struct.MutexGuard.html) | No | Yes (if `T` is `Sync`) | single | Yes\n[`Cell\u003cT\u003e`](https://doc.rust-lang.org/std/cell/struct.Cell.html) | Yes (if `T` is `Send` | No | single | Yes\n[`RefCell\u003cT\u003e`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) | Yes (if `T` is `Send`) | No | single | Yes\n\n## Concurrency models\n\nModel | Description\n------- | -------\nshared memory | threads operate on regions of shared memory\nworker pools | many identical threads receive jobs from a shared job queue\nactors | many different job queues, one for each actor; actors communicate exclusively by exchanging messages\n\nRuntime | Description\n------- | -------\n[tokio](https://crates.io/crates/tokio) (multithreaded) | thread pool with work-stealing scheduler: each processor maintains its own run queue; idle processor checks sibling processor run queues, and attempts to steal tasks from them\n[actix_rt](https://docs.rs/actix-rt/latest/actix_rt/) | single-threaded async runtime; futures are `!Send`\n[actix](https://crates.io/crates/actix) | actor framework\n[actix-web](https://crates.io/crates/actix-web) | constructs an application instance for each thread; application data must be constructed multiple times or shared between threads\n\n## Terminology\n\n**Shared reference**: An immutable reference (`\u0026T`); can be copied/cloned.\n\n**Exclusive reference**: A mutable reference (`\u0026mut T`); cannot be copied/cloned.\n\n**Aliasing**: Having several immutable references.\n\n**Mutability**: Having one mutable reference.\n\n**[Data race](https://doc.rust-lang.org/nomicon/races.html)**: Two or more threads concurrently accessing a location of memory; one or more of them is a write; one or more of them is unsynchronized.\n\n**[Race condition](https://en.wikipedia.org/wiki/Race_condition)**: The condition of a software system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events.\n\n**[Deadlock](https://en.wikipedia.org/wiki/Deadlock)**: Any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action.\n\n**[Heisenbug](https://en.wikipedia.org/wiki/Heisenbug)**: A heisenbug is a software bug that seems to disappear or alter its behavior when one attempts to study it. For example, time-sensitive bugs such as race conditions may not occur when the program is slowed down by single-stepping source lines in the debugger.\n\n**Marker trait**: Used to give the compiler certain guarantees (see [`std::marker`](https://doc.rust-lang.org/std/marker/index.html)).\n\n**Thread**: A native OS thread.\n\n**[Green threads (or virtual threads)](https://en.wikipedia.org/wiki/Green_threads)**: Threads that are scheduled by a runtime library or virtual machine (VM) instead of natively by the underlying operating system (OS).\n\n[**Context switch**](https://en.wikipedia.org/wiki/Context_switch): The process of storing the state of a process or thread, so that it can be restored and resume execution at a later point.\n\n**Synchronous I/O**: blocking I/O.\n\n**Asynchronous I/O**: non-blocking I/O.\n\n**Future** (cf. promise): A single value produced asynchronously.\n\n**Stream**: A series of values produced asynchronously.\n\n**Sink**: Write data asynchronously.\n\n**Task**: An asynchronous green thread.\n\n**Channel**: Enables communication between threads or tasks.\n\n**Mutex** (mutual exclusion): Shares data between threads or tasks.\n\n**Interior mutability**: A design pattern that allows mutating data even when there are immutable references to that data.\n\n**Executor**: Runs asynchronous tasks.\n\n**Generator**: Used internally by the compiler. Can stop (or *yield*) its execution and resume (`poll`) afterwards from its last yield point by inspecting the previously stored state in `self`.\n\n**Reactor**: Leaf futures register event sources with the *reactor*.\n\n**Runtime**: Bundles a reactor and an executor.\n\n**`poll`ing**: Attempts to resolve the future into a final value.\n\n**[io_uring](https://en.wikipedia.org/wiki/Io_uring)**: A Linux kernel system call interface for storage device asynchronous I/O operations.\n\n**[CPU-bound](https://en.wikipedia.org/wiki/CPU-bound)**: Refers to a condition in which the time it takes to complete a computation is determined principally by the speed of the CPU.\n\n**[I/O bound](https://en.wikipedia.org/wiki/I/O_bound)**: Refers to a condition in which the time it takes to complete a computation is determined principally by the period spent waiting for input/output operations to be completed. This is the opposite of a task being CPU bound.\n\n## References\n\n- Steve Klabnik and Carol Nichols, [The Rust Programming Language](https://doc.rust-lang.org/book/)\n- Jon Gjengset, Rust for Rustaceans\n- [The Rustonomicon](https://doc.rust-lang.org/nomicon/intro.html)\n- [Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/)\n- [Tokio tutorial](https://tokio.rs/tokio/tutorial)\n- [Tokio's work-stealing scheduler](https://tokio.rs/blog/2019-10-scheduler#schedulers-how-do-they-work)\n- [Actix user guide](https://actix.rs/book/actix/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquambene%2Frust-concurrency","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquambene%2Frust-concurrency","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquambene%2Frust-concurrency/lists"}