自动更新多个线程之间重叠的向量或切片的正确方法是什么?

时间:2018-11-21 23:48:25

标签: rust

我想对由多个线程共享的向量进行一些工作,但是我不想使用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是否有适当的方法来做到这一点?

我不认为这是How do I pass disjoint slices from a vector to different threads?的副本,因为我的vector / slice元素在线程之间重叠。在我的示例中,切片的每个奇数索引由两个不同的线程递增两次。

1 个答案:

答案 0 :(得分:2)

假设每个线程对向量的特定元素或子片段具有唯一的访问权限,则使用split_at(或类似功能之一)会是这种情况。 split_at将可变切片分为两个独立的可变切片;您可以多次调用它,以将切片分割成正确数量的段,并将每个子切片传递到单独的线程。

将子切片传递给线程的最佳方法是使用类似crossbeam中的作用域线程之类的东西。