Rust 如何将不相交的切片从向量传递到不同的线程?

Rust 如何将不相交的切片从向量传递到不同的线程?,rust,Rust,我是一个新的生锈,并努力处理所有这些包装类型的生锈。我试图编写语义上与下面的C代码相同的代码。代码试图创建一个用于簿记的大表,但会分割该大表,以便每个线程只访问该表的本地小部分。除非其他线程退出并不再访问自己的切片,否则不会访问大表 #包括 #包括 void*写入片(void*arg){ int*切片=(int*)arg; int i; 对于(i=0;i

我是一个新的生锈,并努力处理所有这些包装类型的生锈。我试图编写语义上与下面的C代码相同的代码。代码试图创建一个用于簿记的大表,但会分割该大表,以便每个线程只访问该表的本地小部分。除非其他线程退出并不再访问自己的切片,否则不会访问大表

#包括
#包括
void*写入片(void*arg){
int*切片=(int*)arg;
int i;
对于(i=0;i<10;i++)
切片[i]=i;
返回NULL;
}
int main()
{
int*table=(int*)malloc(100*sizeof(int));
int*切片[10];
int i;
对于(i=0;i<10;i++){
切片[i]=表格+i*10;
}
//为每个切片创建pthread
pthread_t p[10];
对于(i=0;i<10;i++)
pthread_create(&p[i],NULL,write_slice,slice[i]);
对于(i=0;i<10;i++)
pthread_join(p[i],NULL);
对于(i=0;i<100;i++)
printf(“%d”,表[i]);
}

如何使用Rust的类型和所有权来实现这一点?

让我们从代码开始:

//货物部门:横梁=“0.7.3”
外板条箱横梁;
常量块:usize=10;
常量块大小:usize=10;
fn main(){
让mut table=[0;CHUNKS*CHUNK_SIZE];
//作用域线程允许编译器证明任何线程都不会过期
//桌子(那会很糟糕)。
让|=横梁::范围(|范围|{
//将“table”切分为不相交的子切片。
对于表中的切片。chunks\u mut(CHUNK\u SIZE){
//生成一个在该子片上操作的线程。
scope.spawn(移动| |写入|切片(切片));
}
//`crossbeam::scope`确保*all*派生线程在
//从此关闭返回控件。
});
//此时,所有线程都已加入,我们可以独占访问
//再次使用'table'。Huzzah,用于100%安全的多线程堆栈突变!
println!(“{:?},&表[…]);
}
fn写入\u片(片:&mut[i32]){
对于slice.iter_mut().enumerate()中的(i,e){
*e=i为i32;
}
}
需要注意的一点是,这需要板条箱。Rust过去有一个类似的“范围”构造,但在1.0之前就发现了一个健全性漏洞,因此它被弃用,没有时间替换它<代码>横梁基本上是替代品

Rust让您在这里做的是表达这样一种想法:无论代码做什么,在调用
crossbeam::scoped
时创建的线程都不会在该范围内生存。因此,从该范围之外借用的任何内容都将比线程寿命更长。因此,线程可以自由地访问这些借来的内容,而不必担心诸如超出堆栈框架的线程之类的事情,该堆栈框架由堆栈定义并在堆栈上涂鸦

因此,这应该与C代码的功能大致相同,但不必担心您可能遗漏了某些内容

最后,这里使用的是相同的东西。唯一实际的区别是,这允许我们控制使用多少线程

// cargo-deps: scoped_threadpool="0.1.6"
extern crate scoped_threadpool;

const CHUNKS: usize = 10;
const CHUNK_SIZE: usize = 10;

fn main() {
    let mut table = [0; CHUNKS * CHUNK_SIZE];

    let mut pool = scoped_threadpool::Pool::new(CHUNKS as u32);

    pool.scoped(|scope| {
        for slice in table.chunks_mut(CHUNK_SIZE) {
            scope.execute(move || write_slice(slice));
        }
    });

    println!("{:?}", &table[..]);
}

fn write_slice(slice: &mut [i32]) {
    for (i, e) in slice.iter_mut().enumerate() {
        *e = i as i32;
    }
}

不起作用的锈迹代码、你不了解的文档链接、或者任何表明你试图自己解决这个问题的研究都在哪里?堆栈溢出不是“为我编写代码”服务。的可能重复。这带来了一个有趣的问题:此解决方案不涉及任何原子运算符或保护。rust的线程模型是否提供了线程连接后,其他线程可以看到线程的所有副作用?是否存在这样一种情况:工作线程可以完成,但主线程仍然可以看到未更改的内存?@Lucretiel:我从来没有看到写下明确的保证,但如果不写,线程将被严重破坏。我有理由相信,在子线程终止时同步父线程和子线程就足够了:它们都需要同意子线程已经完成,并且这些写操作在同步之前发生;许多现代线程理论都要求使用原子数据结构(如无锁队列)在线程之间进行通信。我相信
std::thread
使用这样一种机制将返回值从线程传递回
thread.join()
@Lucretiel:主线程观察到来自子线程的“I'm done”信号意味着它还可以看到在该信号之前所做的其他写入操作。不管是否有显式锁;重要的是,双方就各自能看到的时间点达成一致。如果你不相信,你应该提出一个新的问题:我不是专家,评论也不是合适的地方。