Я хочу поработать над вектором, совместно используемым несколькими потоками, но я не хочу использовать Mutex
, потому что он не без ожидания.
Код ниже написан так, как я бы вC.
#![feature(core_intrinsics, ptr_internals)]
use std::intrinsics::atomic_xadd_rel;
use std::ptr::Unique;
use std::thread::spawn;
fn main() {
let mut data = [0; 8];
let mut pool = Vec::with_capacity(8);
for index in 0..8 {
let data_ptr = Unique::new(data.as_mut_ptr());
pool.push(spawn(move || {
println!("Thread {} -> {}", index, unsafe {
atomic_xadd_rel(
data_ptr
.unwrap()
.as_ptr()
.add(if index % 2 != 0 { index - 1 } else { index }),
1,
)
});
}));
}
for work in pool {
work.join().unwrap();
}
println!("Data {:?}", data);
}
Я также написал код, используя только стабильный API:
use std::iter::repeat_with;
use std::sync::atomic::{AtomicUsize, Ordering::*};
use std::sync::Arc;
use std::thread::spawn;
fn main() {
let data = Arc::new(
repeat_with(|| AtomicUsize::new(0))
.take(8)
.collect::<Vec<_>>(),
);
let mut pool = Vec::with_capacity(8);
for index in 0..8 {
let data_clone = data.clone();
pool.push(spawn(move || {
let offset = index - (index % 2 != 0) as usize;
println!(
"Thread {} -> {}",
index,
data_clone[offset].fetch_add(1, Relaxed)
);
}));
}
for work in pool {
work.join().unwrap();
}
println!("Data {:?}", data);
}
Этот код возвращает
Thread 0 -> 0
Thread 1 -> 1
Thread 3 -> 0
Thread 5 -> 1
Thread 7 -> 1
Thread 2 -> 1
Thread 6 -> 0
Thread 4 -> 0
Data [2, 0, 2, 0, 2, 0, 2, 0]
Есть ли правильныйспособ сделать это в Rust?
Я не думаю, что это дубликат Как передать непересекающиеся фрагменты из вектора в разные потоки? , потому что мои элементы вектора / слайса перекрываются между потоками,В моем примере каждый нечетный индекс среза увеличивается вдвое двумя разными потоками.