Suppose we have a Rust program that has many threads that are working to complete a task. But a certain part of the task must be complete before any thread may continue.
With Barrier, part of the standard library, we can force all threads to wait for a certain point to be reached. We use the wait()
function. A Mutex
and Condvar is internally used in the Barrier.
When using threads in Rust, we must add code to set up the threads. We need to create an Arc
and clone it in a vector, then spawn a thread for each vector element.
Arc
.Arc
of the Barrier in each element, and spawn a thread for each element.wait()
call that calls the Barrier wait function.use std::sync::*; use std::thread; fn main() { // Step 1: place a Barrier in an Arc, and clone one Arc into each element of an array. let thread_count = 8; let shared = Barrier::new(thread_count); let mut v = vec![]; let arc = Arc::new(shared); for _ in 0..8 { v.push(arc.clone()); } // Step 2: loop over vector elements, and create thread for each element. let mut children = vec![]; for item in v { children.push(thread::spawn(move || { // Step 3: run some code before the wait() function is called on the Barrier, and some after. println!("Part A"); item.wait(); println!("Part B"); })); } // Step 4: join all threads. for child in children { child.join().ok(); } }Part A Part A Part A Part A Part A Part A Part A Part A Part B Part B Part B Part B Part B Part B Part B Part B
We can see that the "Part A" print statements are all before the "Part B" statements. Each thread blocks until all the "Part A" statements are written.
Barriers are useful for many multi-threaded Rust programs. Suppose we have many worker threads, but one operation must be complete before the next can begin—Barrier is perfect here.