Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Обычные потоки

Потоки Rust работают аналогично потокам в других языках:

// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 0..10 {
            println!("Count in thread: {i}!");
            thread::sleep(Duration::from_millis(5));
        }
    });

    for i in 0..5 {
        println!("Main thread: {i}");
        thread::sleep(Duration::from_millis(5));
    }
}
  • Создание новых потоков не задерживает автоматически завершение программы в конце main.
  • Паники потоков независимы друг от друга.
    • Паника может нести полезную нагрузку (payload), которую можно извлечь с помощью Any::downcast_ref.
This slide should take about 15 minutes.
  • Запустите пример.

    • Задержки в 5 мс достаточно велики, чтобы main и порождённые потоки в основном шли в ногу.
    • Обратите внимание, что программа завершается до того, как порождённый поток дойдёт до 10!
    • Это потому, что main завершает программу, а порождённые потоки её не продлевают.
      • При желании сравните с pthreads/std::thread в C++/boost::thread.
  • Как дождаться завершения порождённого потока?

  • thread::spawn возвращает JoinHandle. Посмотрите документацию.

    • У JoinHandle есть метод .join(), который блокирует выполнение.
  • Используйте let handle = thread::spawn(...), а затем handle.join(), чтобы дождаться завершения потока и дать программе досчитать до 10.

  • А если мы хотим вернуть значение?

  • Снова посмотрите документацию:

    • Замыкание, переданное в thread::spawn, возвращает T
    • JoinHandle .join() возвращает thread::Result<T>
  • Используйте возвращаемое значение Result из handle.join(), чтобы получить доступ к возвращённому значению.

  • Хорошо, а как насчёт другого случая?

    • Вызовите панику в потоке. Обратите внимание, что это не вызывает панику в main.
    • Получите доступ к полезной нагрузке паники. Сейчас хорошее время поговорить о Any.
  • Теперь мы можем возвращать значения из потоков! А как насчёт передачи входных данных?

    • Захватите что-нибудь по ссылке в замыкании потока.
    • Сообщение об ошибке говорит, что это нужно переместить (move).
    • Переместите значение внутрь и убедитесь, что можно вычислить и затем вернуть производное значение.
  • А если мы хотим заимствовать?

    • main завершает дочерние потоки при возврате, но если бы другая функция просто вернула управление, они продолжили бы работать.
    • Это было бы использование стека после возврата (stack use-after-return), что нарушает безопасность памяти!
    • Как этого избежать? См. следующий слайд.