如何跨线程共享包含 Sender 和 Receiver 字段的结构体?

问题描述 投票:0回答:2

我有一个结构,大致如下

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
,因为我只会有一个线程使用它。
    

multithreading rust channel
2个回答
0
投票
https://stackoverflow.com/a/65354846/6070255

您可以使用标准库中的
std::sync::mpsc::SyncSender

。不同之处在于它实现了 Sync 特性,但如果发送消息时内部缓冲区没有空间,它可能会阻塞。

欲了解更多信息:

    std::同步::mpsc::通道
  • std::sync::mpsc::sync_channel

0
投票
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(); });

© www.soinside.com 2019 - 2024. All rights reserved.