@@ -822,9 +822,14 @@ const NOTIFIED: usize = 2;
822822/// In other words, each [`Thread`] acts a bit like a spinlock that can be
823823/// locked and unlocked using `park` and `unpark`.
824824///
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+ ///
825830/// The API is typically used by acquiring a handle to the current thread,
826831/// 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
828833/// thread calls [`unpark`] on the handle.
829834///
830835/// The motivation for this design is twofold:
@@ -839,21 +844,33 @@ const NOTIFIED: usize = 2;
839844///
840845/// ```
841846/// use std::thread;
847+ /// use std::sync::{Arc, atomic::{Ordering, AtomicBool}};
842848/// use std::time::Duration;
843849///
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) {
846857/// println!("Parking thread");
847858/// 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.
848861/// println!("Thread unparked");
849- /// })
850- /// .unwrap();
862+ /// }
863+ /// println!("Flag received");
864+ /// });
851865///
852866/// // Let some time pass for the thread to be spawned.
853867/// thread::sleep(Duration::from_millis(10));
854868///
869+ /// // Set the flag, and let the thread wake up.
855870/// // There is no race condition here, if `unpark`
856871/// // happens first, `park` will return immediately.
872+ /// // Hence there is no risk of a deadlock.
873+ /// flag.store(true, Ordering::Release);
857874/// println!("Unpark the thread");
858875/// parked_thread.thread().unpark();
859876///
0 commit comments