前言:
众所周知,rust中要想在线程间传递对象,该对象必须实现Send或者Sync的trait。而裸指针是不能在线程间传递的。但是某些场景下又需要在线程间传递裸指针,比如夸语言编程的时候,需要将一个C的指针在多线程间使用。此时就需要一些技巧了。本文介绍如何在线程间传递裸指针。
一、正常场景
如下述代码所示,一般情况下我们使用多线程move的都是可以Send的对象。此时,该对象会在每个线程中都拷贝一份。所以多线程可以正常运行。
fn main() {
use std::thread;
let num=100;
let mut handles = vec![];
for _ in 0..50 {
let handle = thread::spawn(move|| {
println!("num is {}",num);
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("handle join panic!");
}
}
二、异常场景
如下述代码所示,裸指针不能在多线程间move。这段代码编译时就会报这样的错:
fn main() {
use std::thread;
let ptr:*mut u32 = 12345 as * mut u32;
let mut handles = vec![];
for _ in 0..50 {
let handle = thread::spawn(move|| {
println!("ptr is {:?}",ptr);
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("handle join panic!");
}
}
三、解决方法
自己实现一个结构体,将该裸指针封装在结构体里,并为其实现Send和Copy trait,这样它就能在多线程间传递了。本文给出一个简单的示例,注意大家实际应用时还应该根据具体场景实现诸如引用计数之类的保证安全的机制。
struct MyBox {
v: *mut u32,
}
impl MyBox {
pub fn new(v: *mut u32) -> Self {
Self { v }
}
pub fn get(&self) -> &*mut u32 {
&self.v
}
}
unsafe impl Send for MyBox {}
impl Clone for MyBox {
fn clone(&self) -> Self {
Self { v: self.v.clone() }
}
}
impl Copy for MyBox {}
fn main() {
use std::thread;
let ptr: *mut u32 = 12345 as *mut u32;
let mybox = MyBox::new(ptr);
let mut handles = vec![];
for _ in 0..50 {
let handle = thread::spawn(move || {
println!("ptr is {:?}", mybox.get());
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("handle join panic!");
}
}
参考:rust - Why can't I send Mutex<*mut c_void> between threads? - Stack Overflow