Wait! Don't spawn that task! — Comparing patterns for mutable state in concurrent applications

Using multiple tasks is probably the most common way to perform non-sequential work in Rust. Each task can wait for a different IO event, and the async runtime will schedule the tasks to do work as soon as the IO events occur. This provides for a simple and convenient way to "non-blockingly" wait for these IO events to happen and achieve concurrency. But sharing mutable state among the tasks can…