我正在努力通过频道发送自定义结构。
我按照教程中的说明将值包装在Arc
和Mutex
中,
但它无论如何都不会编译。
extern crate num;
use num::bigint::BigInt;
use std::io::{self, Write};
use std::sync::mpsc;
use std::thread;
use readline::readline as ask;
use std::sync::{Arc, Mutex};
enum Command {
Quit,
Help,
Factorial { n: BigInt },
Error { msg: String },
}
fn main() {
let (input_tx, input_rx) = mpsc::channel();
let input_thread = thread::spawn(|| {
input_tx.send(Arc::new(Mutex::new(Command::Quit)));
});
}
error: the trait bound `std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>: std::marker::Sync` is not satisfied [E0277]
let input_thread = thread::spawn(|| {
^~~~~~~~~~~~~
help: run `rustc --explain E0277` to see a detailed explanation
note: `std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>` cannot be shared between threads safely
note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>`
note: required because it appears within the type `[closure@src/main.rs:25:38: 65:6 input_tx:&std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>]`
note: required by `std::thread::spawn`
error: aborting due to previous error
我正在使用Rust 1.10.0(cfcb716cf 2016-07-03)。
答案 0 :(得分:2)
传递给thread::spawn()
的关闭必须是move
(FnOnce
)。 1}}和Arc
不需要:
Mutex
答案 1 :(得分:1)
看看这个MCVE:
use std::thread;
use std::sync::mpsc;
enum Command {
Quit,
Error { msg: String },
}
fn main() {
let (input_tx, input_rx) = mpsc::channel();
let input_thread = thread::spawn(|| {
input_tx.send(Command::Quit);
});
}
错误信息:
`std :: sync :: mpsc :: Sender`不能安全地在线程之间共享;因为`&amp; std :: sync :: mpsc :: Sender`的`std :: marker :: Send`的impl要求而需要
(强调我的)
默认情况下,闭包会将引用捕获到其中使用的任何变量。这是你大多数时候想要的,因为放弃所有权对于关闭的创建者来说更具限制性。使用引用允许捕获的值在闭包之外和内部之间共享,并且不需要移动任何位。
在这种情况下,您执行希望将input_tx
的所有权授予关闭。这是因为闭包本身的所有权将被赋予一个新线程,因此闭包及其中的所有内容都需要安全地传递给另一个线程。 <{1}}的引用可能不会在线程之间共享。
A move
closure请求将所有捕获变量的所有权转移到闭包。通过这样做,没有共享并且满足所有要求。正如aSpex said:
Sender
有时您需要转移某些捕获变量的所有权,但希望与其他人共享。由于let input_thread = thread::spawn(move || {
input_tx.send(Command::Quit);
});
闭包是全有或全无,在这种情况下你需要更明确。您可以在关闭之前简单地参考:
move
这不起作用,因为对let a = 42;
let a_ref = &a;
let input_thread = thread::spawn(move || {
println!("{}", a_ref);
});
的引用不是a
,而是显示了一般的想法。