Разделяемая оболочка в Rust
Фоновая линия принимает только данные, которые можно безопасно перенести во владение. Обычный счет ссылок на куче в потоки не передают: для совместной работы из нескольких линий нужна оболочка со счетом, рассчитанная на параллельный доступ.
Обернем счетчик во взаимное исключение, положим его в разделяемую оболочку и отдадим копию имени каждой фоновой линии:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared = Arc::new(Mutex::new(0));
let first = Arc::clone(&shared);
let second = Arc::clone(&shared);
let h1 = thread::spawn(move || {
match first.lock() {
Ok(mut guard) => *guard += 1,
Err(_) => {}
}
});
let h2 = thread::spawn(move || {
match second.lock() {
Ok(mut guard) => *guard += 1,
Err(_) => {}
}
});
match h1.join() {
Ok(_) => {}
Err(_) => println!("ожидание вернуло ошибку"),
}
match h2.join() {
Ok(_) => {}
Err(_) => println!("ожидание вернуло ошибку"),
}
match shared.lock() {
Ok(guard) => println!("{}", *guard),
Err(_) => println!("ожидание вернуло ошибку"),
}
}
На экране число 2. Клон оболочки
не копирует число в куче, а лишь добавляет
еще одно имя на тот же замок. Каждая
линия ждет доступ по очереди и увеличивает
общий счет.
Тот же прием с одной фоновой линией и выводом счета ссылок до и после ожидания:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared = Arc::new(Mutex::new(5));
let copy = Arc::clone(&shared);
println!("{}", Arc::strong_count(&shared));
let handle = thread::spawn(move || {
match copy.lock() {
Ok(guard) => println!("{}", *guard),
Err(_) => {}
}
});
match handle.join() {
Ok(_) => {}
Err(_) => println!("ожидание вернуло ошибку"),
}
println!("{}", Arc::strong_count(&shared));
}
Дано число:
let num = 4;
Положите литерал под взаимное исключение, оберните в разделяемую оболочку и выведите сильный счет до запуска фоновой линии.
Скажите, зачем перед запуском линии делают клон разделяемой оболочки, а не передают исходное имя целиком.
Дано число:
let num = 1;
Две фоновые линии по разу увеличивают общий счетчик под одной оболочкой. После ожидания обеих выведите итог.