将 Receiver 移动到线程会抱怨 Sync,但预期会发送
Moving Receiver to thread complains about Sync, but expected Send
我正在尝试通过 Arc
将接收器引用到线程中,这样我就可以通过调度程序进行集中式发布-订阅。但是,我收到以下错误:
src/dispatcher.rs:58:11: 58:24 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` [E0277]
src/dispatcher.rs:58 thread::spawn(move || {
^~~~~~~~~~~~~
src/dispatcher.rs:58:11: 58:24 note: `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` cannot be shared between threads safely
src/dispatcher.rs:58 thread::spawn(move || {
哇!我以为跨频道只需要Send
? DispatchMessage
的代码是:
#[derive(PartialEq, Debug, Clone)]
enum DispatchType {
ChangeCurrentChannel,
OutgoingMessage,
IncomingMessage
}
#[derive(Clone)]
struct DispatchMessage {
dispatch_type: DispatchType,
payload: String
}
String
和肯定 Enum
都是 Send
,对吧?为什么抱怨Sync
?
调度相关部分:
pub fn start(&self) {
let shared_subscribers = Arc::new(self.subscribers);
for ref broadcaster in &self.broadcasters {
let shared_broadcaster = Arc::new(Mutex::new(broadcaster));
let broadcaster = shared_broadcaster.clone();
let subscribers = shared_subscribers.clone();
thread::spawn(move || {
loop {
let message = &broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster");
match subscribers.get(type_to_str(&message.dispatch_type)) {
Some(ref subs) => {
for sub in subs.iter() { sub.send(*message).unwrap(); }
},
None => ()
}
}
});
}
}
完整的调度程序代码在这个要点中:https://gist.github.com/timonv/5cdc56bf671cee69d3fa
如果它仍然相关,则针对 5-2-2015 每晚构建。
Arc
需要 Sync
,在我看来您正试图将频道放入 Arc
。频道不是 Sync
、Sender
或 Receiver
。
在不知道您要做什么的情况下,以下几点可能对您有所帮助:
- 可以克隆
Sender
,因此您可能 Arc
一个 T
并在多个线程之间共享它,您可以克隆一个 Sender
并发送它有很多线程,因为它 是 Send
- 否则(尤其是对于
Receiver
,您无法克隆)您必须将其粘贴在 Arc<Mutex<T>>
中,这使得它成为 Sync
.
尽管 Jorge 在一般意义上是正确的,但此特定代码的问题在于创建 Arc Mutex 会获取参数的所有权,因此不能作为引用。当您考虑时,这是有道理的。你怎么能锁上不属于你的东西?或者更具体地说,我们需要锁定该内存位置的任何内容,而不是指向它的指针。
在将广播器添加到结构时更改代码以创建 Arc Mutex 解决了问题。这会将那部分代码更改为:
pub fn register_broadcaster(&mut self, broadcaster: &mut Broadcast) {
let handle = Arc::new(Mutex::new(broadcaster.broadcast_handle()));
self.broadcasters.push(handle);
}
然后调度程序的启动方法如下所示:
pub fn start(&self) {
// Assuming that broadcasters.clone() copies the vector, but increase ref count on els
for broadcaster in self.broadcasters.clone() {
let subscribers = self.subscribers.clone();
thread::spawn(move || {
loop {
let message = broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster or channel hung up");
match subscribers.get(type_to_str(&message.dispatch_type)) {
Some(ref subs) => {
for sub in subs.iter() { sub.send(message.clone()).unwrap(); }
},
None => ()
}
}
});
}
}
我正在尝试通过 Arc
将接收器引用到线程中,这样我就可以通过调度程序进行集中式发布-订阅。但是,我收到以下错误:
src/dispatcher.rs:58:11: 58:24 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` [E0277]
src/dispatcher.rs:58 thread::spawn(move || {
^~~~~~~~~~~~~
src/dispatcher.rs:58:11: 58:24 note: `core::cell::UnsafeCell<std::sync::mpsc::Flavor<dispatcher::DispatchMessage>>` cannot be shared between threads safely
src/dispatcher.rs:58 thread::spawn(move || {
哇!我以为跨频道只需要Send
? DispatchMessage
的代码是:
#[derive(PartialEq, Debug, Clone)]
enum DispatchType {
ChangeCurrentChannel,
OutgoingMessage,
IncomingMessage
}
#[derive(Clone)]
struct DispatchMessage {
dispatch_type: DispatchType,
payload: String
}
String
和肯定 Enum
都是 Send
,对吧?为什么抱怨Sync
?
调度相关部分:
pub fn start(&self) {
let shared_subscribers = Arc::new(self.subscribers);
for ref broadcaster in &self.broadcasters {
let shared_broadcaster = Arc::new(Mutex::new(broadcaster));
let broadcaster = shared_broadcaster.clone();
let subscribers = shared_subscribers.clone();
thread::spawn(move || {
loop {
let message = &broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster");
match subscribers.get(type_to_str(&message.dispatch_type)) {
Some(ref subs) => {
for sub in subs.iter() { sub.send(*message).unwrap(); }
},
None => ()
}
}
});
}
}
完整的调度程序代码在这个要点中:https://gist.github.com/timonv/5cdc56bf671cee69d3fa
如果它仍然相关,则针对 5-2-2015 每晚构建。
Arc
需要 Sync
,在我看来您正试图将频道放入 Arc
。频道不是 Sync
、Sender
或 Receiver
。
在不知道您要做什么的情况下,以下几点可能对您有所帮助:
- 可以克隆
Sender
,因此您可能Arc
一个T
并在多个线程之间共享它,您可以克隆一个Sender
并发送它有很多线程,因为它 是Send
- 否则(尤其是对于
Receiver
,您无法克隆)您必须将其粘贴在Arc<Mutex<T>>
中,这使得它成为Sync
.
尽管 Jorge 在一般意义上是正确的,但此特定代码的问题在于创建 Arc Mutex 会获取参数的所有权,因此不能作为引用。当您考虑时,这是有道理的。你怎么能锁上不属于你的东西?或者更具体地说,我们需要锁定该内存位置的任何内容,而不是指向它的指针。
在将广播器添加到结构时更改代码以创建 Arc Mutex 解决了问题。这会将那部分代码更改为:
pub fn register_broadcaster(&mut self, broadcaster: &mut Broadcast) {
let handle = Arc::new(Mutex::new(broadcaster.broadcast_handle()));
self.broadcasters.push(handle);
}
然后调度程序的启动方法如下所示:
pub fn start(&self) {
// Assuming that broadcasters.clone() copies the vector, but increase ref count on els
for broadcaster in self.broadcasters.clone() {
let subscribers = self.subscribers.clone();
thread::spawn(move || {
loop {
let message = broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster or channel hung up");
match subscribers.get(type_to_str(&message.dispatch_type)) {
Some(ref subs) => {
for sub in subs.iter() { sub.send(message.clone()).unwrap(); }
},
None => ()
}
}
});
}
}