我有一个结构,大致如下
struct Node {
id: Arc<i32>,
data: Arc<Mutex<i32>>, // Actually not i32, but that is not important for this question.
rx: Receiver<()>,
tx: Sender<()>
}
我使用
Receiver
和 Sender
中的 mpsc::channel
。
我想跨多个线程共享此内容。我有一个“用户”线程,其中
Node
的用户在 Node
上执行一些功能。这将导致一些 UDP 消息被发送到其他计算机,并且该线程将在 rx.recv()
上阻塞。在后台,我有一个或多个线程在 UDP 套接字上执行阻塞接收调用。当它们收到消息时,它们会更新 data
结构体的 Node
字段,当后台线程注意到已收到足够多的消息时,它将使用 ()
发送 tx.send()
,让用户线程继续它的执行。要将
Node
实例共享给另一个线程,我会执行以下操作:
let node: Arc<Node> = ...
let node_for_background_thread = Arc::clone(&node);
let background_thread_handle = thread::spawn(move || {
node_for_background_thread.start_receive_loop();
});
我需要在用户线程和后台线程中访问
Node
的所有字段(例如
id
和 data
)。这就是为什么我想在他们之间共享一个 Node
实例。但 Receiver
和 Sender
都不是 Sync
,所以上面的代码无法编译。我知道我可以克隆 Sender
将其中一个拥有的放入每个后台线程中。我看到的一个解决方案是不将
rx
和
tx
包含在 Node
中。但这样我就会失去封装,因为 Node
实例的创建者必须创建通道并生成后台线程。如果可能的话,我想将它们全部封装在 Node
中。上面的代码片段是我可以手动克隆
Sender
的地方。我不需要克隆
Receiver
,因为我只会有一个线程使用它。std::sync::mpsc::SyncSender。不同之处在于它实现了
欲了解更多信息:Sync
特性,但如果发送消息时内部缓冲区没有空间,它可能会阻塞。
Arc
中,这很容易,您也可以将
Receiver
包装到 Arc<Mutex<~>>
中(当然,使用 Receiver
意味着像 中的那样进行共享) crossbeam
会更好)。 Sender
已经设计用于克隆。然后,您无需传递引用,只需直接 clone
Node
,不再需要包裹在 Arc
中:#[derive(Clone)]
struct Node {
id: Arc<i32>,
data: Arc<Mutex<i32>>, // Actually not i32, but that is not important for this question.
rx: Arc<Mutex<Receiver<()>>>,
tx: Sender<()>
}
并分享:
let node: Node = ...
let node_for_background_thread = node.clone();
let background_thread_handle = thread::spawn(move || {
node_for_background_thread.start_receive_loop();
});