Барьеры

Последнее обновление: 17.05.2024

Когда в программе используется несколько потоков, выполняющих задачи, которые зависят от завершения друг друга, то на первый план выходит проблема координации потоков. Rust предоставляет удобный способ координации потоков с помощью барьеров из модуля std::sync.

Барьеры могут помочь эффективно координировать потоки, гарантируя, что они синхронизируют свою работу в определенных точках программы. Такая координация имеет решающее значение для сценариев, в которых разные потоки должны сотрудничать для достижения общей цели, например, для параллельной обработки, планирования задач или распределенных вычислений.

Рассмотрим небольшой пример:

use std::sync::{Arc, Barrier};
use std::thread;

fn main() {

    // создаем барьер
    // число 3 указывает, что барьер должен ждать завершения 3 потоков
    let barrier = Arc::new(Barrier::new(3));

    let mut threads = vec![];

    // создаем 3 потока
    for id in 0..3 {

        // клонируем барьер для передачи в поток
        let barrier = Arc::clone(&barrier);
        // создаем поток
        let new_thread = thread::spawn(move || {

            println!("Thread {} started", id);
            thread::sleep(std::time::Duration::from_secs(2)); // имитация работы
            println!("Thread {} finished", id);
            // ожидаем завершения других потоков
            barrier.wait();

            println!("Thread {} reached the barrier", id);
        });

        threads.push(new_thread);
    }

    // ждем завершения потоков
    for t in threads { t.join().unwrap(); }
}

Здесь мы создаем барьер со счетчиком 3, указывая, что он должен дождаться, пока три потока достигнут его, прежде чем разрешить им продолжить работу:

let barrier = Arc::new(Barrier::new(3));

Опять же обертываем барьер в Arc для использования в других потоках.

Далее для демонстрации запускаем 3 потока, передавая в каждый из них копию барьера.

let barrier = Arc::clone(&barrier);
let new_thread = thread::spawn(move || {
    
    println!("Thread {} started", id);
    thread::sleep(std::time::Duration::from_secs(2)); // имитация работы
    println!("Thread {} finished", id);

Для имитации работы каждого потока используется задержка в 2 секунды. А затем поток ждет, пока другие потоки достигнут барьера:

barrier.wait();

Пример результата работы программы:

Thread 0 started
Thread 1 started
Thread 2 started
Thread 0 finished
Thread 2 finished
Thread 1 finished
Thread 1 reached the barrier
Thread 2 reached the barrier
Thread 0 reached the barrier
Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850