Rust Concurrency
- Example 1: Multi-Threading Counter
- Example 2: Fire and Forget Thread
- Example 3: Loop
- Example 4: Clipboard Watcher
Example 1: Multi-Threading Counter
Naive Approach
Here is a multi-threading counter. count will be 0, because count is not shared between threads. The "move" keyword moves the ownership of count to the thread.
Arc + Mutex Approach
Example 2: Fire and Forget Thread
In JavaScript, promise can be fired and forgotten. In Rust, we can use thread::spawn to create a fire and forget thread.
A Tokio Example
Fire and Forget Thread in a Struct
Optional: Wait for Thread to Finish with thread
You may want to wait for the thread to finish in the main thread (while keeping the option to fire and forget), use the returned JoinHandle.
Optional: Wait for Thread to Finish with tokio async await
Then in main thread you can choose to use or not use .await
.
Example 3: Loop
Now I want to run a loop in a separate thread to refresh the system every second.
What if I want to be able to stop the loop when I want to?
tokio's JoinHandle
provides a method abort
to stop the task at any time.
Provide stop
method in System (tokio)
Rather than calling handle.abort()
in main thread, we can provide a stop
method in System
to stop the refresh task.
We can have an extra private field refresh_handle
in System
to store the JoinHandle
.
This can also be used to check if the refresh task is already running. If None, then start the task, otherwise, print a message and return.
The Thread Way to Stop (with a flag)
Unfortunately, thread does not have an abort
method. We can use a bool
flag to stop the loop.
AtomicBool (std::sync::atomic::AtomicBool)
: Atomic types provide atomic operations without needing a lock. They allow safe concurrent access to shared data without the need for explicit locking. AtomicBool specifically provides atomic boolean operations like load, store, compare-and-swap (CAS), etc. It's useful for simple cases where you need to share a boolean flag among threads and want to perform atomic operations on it without the overhead of locking.
Example 4: Clipboard Watcher
This will be a larger example, go to clipboard-watcher.md;
I discuss how to implement a clipboard watcher (or any other event listener) in Rust.
The following topics are covered
- Creating callback functions
- Using trait to define handlers
- Using trait to handle multi-platform implementation of the watcher
- Using Arc + Mutex to share data between threads
- Rust generics
- How to stop a watcher thread using
- Channel
- Flag (
AtomicBool
) abort()
of tokio'sJoinHandle
How is this guide?