Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何使用mpsc通道在线程之间创建环形通信?_Multithreading_Rust_Channel - Fatal编程技术网

Multithreading 如何使用mpsc通道在线程之间创建环形通信?

Multithreading 如何使用mpsc通道在线程之间创建环形通信?,multithreading,rust,channel,Multithreading,Rust,Channel,我希望生成n个线程,使其能够与环形拓扑中的其他线程通信,例如,线程0可以向线程1发送消息,线程1向线程2发送消息,等等,线程n向线程0发送消息 这是我想用n=3实现的一个示例: 使用std::sync::mpsc:{self,Receiver,Sender}; 使用std::线程; let(tx0,rx0):(发送方,接收方)=mpsc::channel(); let(tx1,rx1):(发送方,接收方)=mpsc::channel(); let(tx2,rx2):(发送方,接收方)=mpsc:

我希望生成n个线程,使其能够与环形拓扑中的其他线程通信,例如,线程0可以向线程1发送消息,线程1向线程2发送消息,等等,线程n向线程0发送消息

这是我想用n=3实现的一个示例:

使用std::sync::mpsc:{self,Receiver,Sender};
使用std::线程;
let(tx0,rx0):(发送方,接收方)=mpsc::channel();
let(tx1,rx1):(发送方,接收方)=mpsc::channel();
let(tx2,rx2):(发送方,接收方)=mpsc::channel();
让child0=thread::spawn(移动| |){
tx0.send(0.unwrap();
println!(“线程0已发送:0”);
println!(“线程0 recv:{:?}”,rx2.recv().unwrap());
});
让child1=thread::spawn(移动| |){
tx1.send(1.unwrap();
println!(“线程1已发送:1”);
println!(“线程1 recv:{:?}”,rx0.recv().unwrap());
});
让child2=thread::spawn(移动| |){
tx2.send(2.unwrap();
println!(“线程2已发送:2”);
println!(“线程2 recv:{:?}”,rx1.recv().unwrap());
});
child0.join();
child1.join();
child2.join();
在这里,我在一个循环中创建通道,将它们存储在一个向量中,对发送器重新排序,将它们存储在一个新的向量中,然后生成线程,每个线程都有自己的发送器-接收器(tx1/rx0、tx2/rx1等)对

const-NTHREADS:usize=8;
//创建n个通道
let频道:Vec=
(0..NTHREADS).into_iter().map(| | mpsc::channel()).collect();
//用于发送方创建环形拓扑的开关元组条目
让多个通道_环:Vec=(0..NTHREADS)
.into_iter()
.map(|i|{
(
通道[如果i
这不起作用,因为无法复制发送方来创建新向量。 但是,如果我使用refs(发送方):

let mut channels\u ring:Vec=(0..NTHREADS)
.into_iter()
.map(|i|{
(
&通道[如果i
我无法生成线程,因为无法在线程之间安全地共享
std::sync::mpsc::Sender

这不起作用,因为无法复制发送方来创建新向量。但是,如果使用引用(&S):

虽然
发送方
确实无法复制,但它确实实现了
克隆
,因此您始终可以手动克隆它。但是这种方法不适用于
接收器
,它不是
克隆
,而且还需要从向量中提取

第一个代码的问题是不能使用
let foo=vec[i]
从非
Copy
值的向量中只移动一个值。这将使向量处于无效状态,其中一个元素无效,随后对该元素的访问将导致未定义的行为。为此,
Vec
需要跟踪哪些元素被移动了,哪些元素没有移动,这将给所有
Vec
带来成本。因此,相反,
Vec
不允许从中移出元素,让用户跟踪移动

将值移出
Vec
的一种简单方法是将
Vec
替换为
Vec
,然后使用
foo=vec[i]
替换为
foo=vec[i].take().unwrap()
,它从
vec[i]
中的选项中移动
T
值(同时声明它不是
None
),并在向量中保留
None
,这是
选项的有效变体。这是您第一次尝试以这种方式修改():

const-NTHREADS:usize=8;
让通道振铃:Vec={
让多个通道:Vec=(0..NTHREADS)
.into_iter()
.地图{
let(tx,rx)=mpsc::channel();
(一些(发送),一些(接收))
})
.收集();
(0..NTHREADS)
.into_iter()
.map(| rxpos |{
设txpos=if rxpos
发送方
s和
接收方
s无法共享,因此您需要将它们移动到各自的线程中。这意味着从
Vec
中删除它们,或者在迭代过程中使用
Vec
——即使作为中间步骤,也不允许向量处于无效状态(带孔)。用
迭代向量到iter
将通过使用它们来实现这一点

让发送方和接收方在一个周期内配对的一个小技巧是创建两个向量;一个发送方和一个接收方;然后旋转一个,这样每个向量中的相同索引将为您提供所需的对

use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;

fn main() {
    const NTHREADS: usize = 8;

    // create n channels
    let (mut senders, receivers): (Vec<Sender<i32>>, Vec<Receiver<i32>>) =
        (0..NTHREADS).into_iter().map(|_| mpsc::channel()).unzip();

    // move the first sender to the back
    senders.rotate_left(1);

    let children: Vec<_> = senders
        .into_iter()
        .zip(receivers.into_iter())
        .enumerate()
        .map(|(i, (tx, rx))| {
            thread::spawn(move || {
                tx.send(i as i32).unwrap();
                println!("thread {} sent: {}", i, i);
                println!("thread {} recv: {:?}", i, rx.recv().unwrap());
            })
        })
        .collect();

    for child in children {
        let _ = child.join();
    }
}
使用std::sync::mpsc:{self,Receiver,Sender};
使用std::线程;
fn main(){
常数n:usize=8;
//创建n个通道
let(mut发送方、接收方):(Vec、Vec)=
(0..NTHREADS).into_iter().map(| | mpsc::channel()).unzip();
//将第一个发送器移到后面
发送器。向左旋转(1);
让子项:Vec=发送者
.into_iter()
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;

fn main() {
    const NTHREADS: usize = 8;

    // create n channels
    let (mut senders, receivers): (Vec<Sender<i32>>, Vec<Receiver<i32>>) =
        (0..NTHREADS).into_iter().map(|_| mpsc::channel()).unzip();

    // move the first sender to the back
    senders.rotate_left(1);

    let children: Vec<_> = senders
        .into_iter()
        .zip(receivers.into_iter())
        .enumerate()
        .map(|(i, (tx, rx))| {
            thread::spawn(move || {
                tx.send(i as i32).unwrap();
                println!("thread {} sent: {}", i, i);
                println!("thread {} recv: {:?}", i, rx.recv().unwrap());
            })
        })
        .collect();

    for child in children {
        let _ = child.join();
    }
}