🔀 Rust 并行优势
Rust 的所有权系统保证线程安全,编译时检测数据竞争:
🔒 编译时保证
- 不可能发生数据竞争
- Send trait 保证线程安全传递
- Sync trait 保证线程安全共享
📊 使用 rayon 并行迭代
rust
use neon::prelude::*;
use rayon::prelude::*;
fn parallel_process(mut cx: FunctionContext) -> JsResult {
// 获取输入数组
let input: Vec = cx.argument::(0)?
.to_vec(&mut cx)?
.iter()
.map(|v| v.downcast::(&mut cx).unwrap().value(&mut cx) as i32)
.collect();
// 并行处理
let result: Vec = input.into_par_iter()
.map(|x| x * x) // 并行计算平方
.collect();
// 返回结果
let arr = cx.empty_array();
for (i, val) in result.iter().enumerate() {
arr.set(&mut cx, i as u32, cx.number(*val as f64))?;
}
Ok(arr)
}
📡 Channel 通信
跨线程通信使用 Channel:
rust
use neon::prelude::*;
use std::thread;
use std::sync::mpsc;
fn background_task(mut cx: FunctionContext) -> JsResult {
let channel = cx.channel();
let (tx, rx) = mpsc::channel();
// 启动后台线程
thread::spawn(move || {
let result = expensive_computation();
tx.send(result).unwrap();
});
// 主线程继续
// 可以定期检查 rx 或使用 callback
Ok(cx.undefined())
}
⚠️ 注意事项
🚫 不要在非主线程访问 JS 对象
- JavaScript 对象只能在主线程访问
- 使用 Channel 跨线程传递数据
- 使用 cx.channel() 回调主线程
rust
// ❌ 错误:在子线程访问 JS 对象
fn bad_example(mut cx: FunctionContext) -> JsResult {
let obj = cx.argument::(0)?;
thread::spawn(move || {
// 错误!obj 不能跨线程传递
let _ = obj.get(&mut cx, "key");
});
Ok(cx.undefined())
}
// ✅ 正确:先提取数据
fn good_example(mut cx: FunctionContext) -> JsResult {
let obj = cx.argument::(0)?;
let data = obj.get::(&mut cx, "key")?.value(&mut cx);
thread::spawn(move || {
// 使用 data 字符串
println!("{}", data);
});
Ok(cx.undefined())
}