@@ -822,9 +822,14 @@ const NOTIFIED: usize = 2;
822
822
/// In other words, each [`Thread`] acts a bit like a spinlock that can be
823
823
/// locked and unlocked using `park` and `unpark`.
824
824
///
825
+ /// Notice that being unblocked does not imply any synchronization with someone
826
+ /// that unparked this thread, it could also be spurious.
827
+ /// For example, it would be a valid, but inefficient, implementation to make both [`park`] and
828
+ /// [`unpark`] return immediately without doing anything.
829
+ ///
825
830
/// The API is typically used by acquiring a handle to the current thread,
826
831
/// placing that handle in a shared data structure so that other threads can
827
- /// find it, and then `park`ing. When some desired condition is met, another
832
+ /// find it, and then `park`ing in a loop . When some desired condition is met, another
828
833
/// thread calls [`unpark`] on the handle.
829
834
///
830
835
/// The motivation for this design is twofold:
@@ -839,21 +844,33 @@ const NOTIFIED: usize = 2;
839
844
///
840
845
/// ```
841
846
/// use std::thread;
847
+ /// use std::sync::{Arc, atomic::{Ordering, AtomicBool}};
842
848
/// use std::time::Duration;
843
849
///
844
- /// let parked_thread = thread::Builder::new()
845
- /// .spawn(|| {
850
+ /// let flag = Arc::new(AtomicBool::new(false));
851
+ /// let flag2 = Arc::clone(&flag);
852
+ ///
853
+ /// let parked_thread = thread::spawn(move || {
854
+ /// // We want to wait until the flag is set. We *could* just spin, but using
855
+ /// // park/unpark is more efficient.
856
+ /// while !flag2.load(Ordering::Acquire) {
846
857
/// println!("Parking thread");
847
858
/// thread::park();
859
+ /// // We *could* get here spuriously, i.e., way before the 10ms below are over!
860
+ /// // But that is no problem, we are in a loop until the flag is set anyway.
848
861
/// println!("Thread unparked");
849
- /// })
850
- /// .unwrap();
862
+ /// }
863
+ /// println!("Flag received");
864
+ /// });
851
865
///
852
866
/// // Let some time pass for the thread to be spawned.
853
867
/// thread::sleep(Duration::from_millis(10));
854
868
///
869
+ /// // Set the flag, and let the thread wake up.
855
870
/// // There is no race condition here, if `unpark`
856
871
/// // happens first, `park` will return immediately.
872
+ /// // Hence there is no risk of a deadlock.
873
+ /// flag.store(true, Ordering::Release);
857
874
/// println!("Unpark the thread");
858
875
/// parked_thread.thread().unpark();
859
876
///
0 commit comments