В главе 20 The Rust Book приведен пример реализации пул потоков построен. Задания передаются рабочим через канал с одним производителем и несколькими потребителями: у каждого рабочего есть Arc<Mutex<Receiver>>
для выбора заданий из очереди.
Первый пример тела рабочего потока выглядит так:
loop {
let job = receiver.lock().unwrap().recv().unwrap();
println!("Worker {} got a job; executing.", id);
job();
}
Когда я увидел это, моей первой мыслью было «но мьютекс удерживается, пока job
запущен» (т.е. я не ожидал, что мьютекс будет выпущен до тех пор, пока возвращаемое значение lock
не выйдет из области видимости в конце цикла).
Однако в книге приводится второй пример:
while let Ok(job) = receiver.lock().unwrap().recv() {
println!("Worker {} got a job; executing.", id);
job();
}
В книге говорится, что этот пример демонстрирует описанную мною проблему, то есть "блокировка остается в силе на время вызова job()
". Далее говорится, что в предыдущем примере проблема не возникает, потому что «MutexGuard
, возвращенный из метода lock
, отбрасывается, как только оператор let job
завершается».
Эта последняя часть заставляет звучать так, как будто, поскольку MutexGuard
на самом деле никогда не присваивается переменной, его время жизни заканчивается, как только выражение завершает вычисление. Это имело бы смысл. Но разве это не относится ко второму примеру? Почему нахождение в while
выражении изменяет время жизни значения MutexGuard
?