如何跨线程共享包含发送方和接收方字段的结构?

时间:2019-07-08 14:20:27

标签: multithreading rust channel

我有一个结构大致如下

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中的Sendermpsc::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的所有字段(例如iddata)。这就是为什么我要在它们之间共享Node的单个实例。但是ReceiverSender都不是Sync,因此上述内容无法编译。我知道我可以克隆Sender并将其拥有的一个放入每个后台线程。

我看到的一种解决方案是在rx中不包含txNode。但是然后我将丢失封装,因为Node实例的创建者将不得不创建通道并生成后台线程。我想尽可能将它们全部封装在Node中。

上面的代码片段是我可以手动克隆Sender的地方。我不需要克隆Receiver,因为我只有一个线程可以使用它。

1 个答案:

答案 0 :(得分:0)

我在这里回答:https://stackoverflow.com/a/65354846/6070255

您可以使用标准库中的std::sync::mpsc::SyncSender。区别在于它实现了Sync特性,但是如果在发送消息时内部缓冲区中没有空间,它将阻塞。

有关更多信息: