use*_*021 2 multithreading rust
我是Rust和线程的新手,我正在尝试打印一个数字,同时在另一个线程中添加它.我怎么能做到这一点?
use std::thread;
use std::time::Duration;
fn main() {
let mut num = 5;
thread::spawn(move || {
loop {
num += 1;
thread::sleep(Duration::from_secs(10));
}
});
output(num);
}
fn output(num: i32) {
loop {
println!("{:?}", num);
thread::sleep(Duration::from_secs(5));
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不起作用:它总是打印5,好像数字永远不会增加.
请阅读The Rust Book的"并发"章节"安全共享可变状态"部分,它将详细说明如何执行此操作.
简而言之:
num被复制而不起作用,因此output()线程在该号码的不同副本上运行.如果num不可复制,Rust编译器将无法编译并出现错误.Arc(一个托米奇ř eference- Ç ounted变量)Arc,你需要把它放在一个Mutex或RwLock.您可以使用该.lock()方法从a中获取可变引用Mutex.该方法将确保在该可变引用的生命周期内对整个过程的独占访问.use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let num = Arc::new(Mutex::new(5));
// allow `num` to be shared across threads (Arc) and modified
// (Mutex) safely without a data race.
let num_clone = num.clone();
// create a cloned reference before moving `num` into the thread.
thread::spawn(move || {
loop {
*num.lock().unwrap() += 1;
// modify the number.
thread::sleep(Duration::from_secs(10));
}
});
output(num_clone);
}
fn output(num: Arc<Mutex<i32>>) {
loop {
println!("{:?}", *num.lock().unwrap());
// read the number.
// - lock(): obtains a mutable reference; may fail,
// thus return a Result
// - unwrap(): ignore the error and get the real
// reference / cause panic on error.
thread::sleep(Duration::from_secs(5));
}
}
Run Code Online (Sandbox Code Playgroud)
您可能还想阅读:
Arc<Mutex<i32>>代替Arc<i32>)Arc<Mutex<i32>>而不是Mutex<i32>)另一个答案解决了任何类型的问题,但正如 pnkfelix观察到的那样,原子包装类型是另一种适用于 的特定情况的解决方案i32。
从 Rust 1.0 开始,您可以使用AtomicBool、AtomicPtr<T>和AtomicIsize来同步对、和值的AtomicUsize多线程访问。在 Rust 1.34 中,几个新类型已经稳定,包括. (查看当前列表的文档。)bool*mut TisizeusizeAtomicAtomicI32std::sync::atomic
使用原子类型很可能比锁定 aMutex或更有效RwLock,但需要更多地关注内存排序的低级细节。如果您的线程共享的数据多于一种标准原子类型所能容纳的数据,您可能需要一个Mutex而不是多个Atomics。
也就是说,这是 kennytm 的答案的一个版本,使用AtomicI32而不是Mutex<i32>:
use std::sync::{
atomic::{AtomicI32, Ordering},
Arc,
};
use std::thread;
use std::time::Duration;
fn main() {
let num = Arc::new(AtomicI32::new(5));
let num_clone = num.clone();
thread::spawn(move || loop {
num.fetch_add(1, Ordering::SeqCst);
thread::sleep(Duration::from_secs(10));
});
output(num_clone);
}
fn output(num: Arc<AtomicI32>) {
loop {
println!("{:?}", num.load(Ordering::SeqCst));
thread::sleep(Duration::from_secs(5));
}
}
Run Code Online (Sandbox Code Playgroud)
Arc共享所有权仍然需要(但请参阅如何将对堆栈变量的引用传递给线程?)。
选择正确的内存Ordering绝非易事。SeqCst是最保守的选择,但如果只有一个内存地址被共享,Relaxed也应该可行。请参阅下面的链接了解更多信息。
std::sync::atomic模块文档| 归档时间: |
|
| 查看次数: |
651 次 |
| 最近记录: |