我是Rust的新手,并努力处理Rust中的所有包装器类型.我试图编写在语义上等于以下C代码的代码.代码尝试创建一个用于簿记的大表,但是会分割大表,以便每个线程只访问该表的本地小片.除非其他线程退出并且不再访问自己的切片,否则不会访问大表.
#include <stdio.h>
#include <pthread.h>
void* write_slice(void* arg) {
int* slice = (int*) arg;
int i;
for (i = 0; i < 10; i++)
slice[i] = i;
return NULL;
}
int main()
{
int* table = (int*) malloc(100 * sizeof(int));
int* slice[10];
int i;
for (i = 0; i < 10; i++) {
slice[i] = table + i * 10;
}
// create pthread for each slice
pthread_t p[10];
for (i = 0; i < 10; i++)
pthread_create(&p[i], NULL, write_slice, slice[i]);
for (i = 0; i < 10; i++)
pthread_join(p[i], NULL);
for (i = 0; i < 100; i++)
printf("%d,", table[i]);
}
Run Code Online (Sandbox Code Playgroud)
如何使用Rust的类型和所有权来实现此目的?
DK.*_*DK. 15
让我们从代码开始:
// cargo-deps: crossbeam="0.7.3"
extern crate crossbeam;
const CHUNKS: usize = 10;
const CHUNK_SIZE: usize = 10;
fn main() {
let mut table = [0; CHUNKS * CHUNK_SIZE];
// Scoped threads allow the compiler to prove that no threads will outlive
// table (which would be bad).
let _ = crossbeam::scope(|scope| {
// Chop `table` into disjoint sub-slices.
for slice in table.chunks_mut(CHUNK_SIZE) {
// Spawn a thread operating on that subslice.
scope.spawn(move |_| write_slice(slice));
}
// `crossbeam::scope` ensures that *all* spawned threads join before
// returning control back from this closure.
});
// At this point, all threads have joined, and we have exclusive access to
// `table` again. Huzzah for 100% safe multi-threaded stack mutation!
println!("{:?}", &table[..]);
}
fn write_slice(slice: &mut [i32]) {
for (i, e) in slice.iter_mut().enumerate() {
*e = i as i32;
}
}
Run Code Online (Sandbox Code Playgroud)
有一点需要注意,这需要crossbeam
箱子.拉斯特使用也有类似的"作用域"建设,而是一个稳健洞被发现右 1.0之前,所以这是没有时间来更换过时. crossbeam
基本上是替代品.
拉斯特什么让你在这里做的是表达的想法,不管代码的功能,没有调用中创建的线程来crossbeam::scoped
将生存该范围.因此,从该范围之外借来的任何东西都会比线程更长寿.因此,线程可以自由地访问那些借用而不必担心诸如线程超出由堆栈table
定义的堆栈帧并在堆栈上乱写的线程.
因此,这应该与C代码或多或少相同,尽管没有令人烦恼的担心你可能错过了一些东西.:)
最后,使用相同的东西scoped_threadpool
.唯一真正的实际区别是,这允许我们控制使用的线程数.
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)