Both async and threads features of Rust may be used separately. However, in this post we will be looking at the synergies of using async with threaded applications.
Rust was built from the ground up with threaded memory sharing at top of mind. Use of threading in applications typically comes with a host of race conditions and possible memory corruption due to thread context-switching. In Rust, most of these problems are prevented through the use of linear-types in the type-checker.
The easiest way to get started with Rust async threads is to declare a function as async. Once a function is declared async, the .await syntax can be used inside of the function to declare that the function must wait for the previous future to end before itself may continue. If a thread is handed a future, then it will return a join handle with a future. If you want to force a thread to join into a parent then you will need to block on its join handle.
It should be warned that if a thread is spawned with an async function, then the async code will not be executed in the spawned thread, but instead after the future has been returned and awaited. This is a potential performance bottleneck that would prevent realizing the gains of asynchronous code across threads.