如何使用 Rust 中的通道菊花链线程?
How to daisy chain threads using channels in Rust?
我正在尝试使用协同程序在 Rust 中实现埃拉托色尼筛法作为学习练习(不是家庭作业),但我找不到任何合理的方法将每个线程连接到 Receiver
和 Sender
两个不同频道的末端。
Receiver
涉及两个不同的任务,即报告目前发现的最高素数,以及为过滤器提供更多候选素数。这是算法的基础。
这是我想做但做不到的,因为接收器不能在线程之间传输。不出所料,使用 std::sync::Arc
似乎没有帮助。
请注意,我明白为什么这不起作用
fn main() {
let (basetx, baserx): (Sender<u32>, Receiver<u32>) = channel();
let max_number = 103;
thread::spawn(move|| {
generate_natural_numbers(&basetx, max_number);
});
let oldrx = &baserx;
loop {
// we need the prime in this thread
let prime = match oldrx.recv() {
Ok(num) => num,
Err(_) => { break; 0 }
};
println!("{}",prime);
// create (newtx, newrx) in a deliberately unspecified way
// now we need to pass the receiver off to the sieve thread
thread::spawn(move || {
sieve(oldrx, newtx, prime); // forwards numbers if not divisible by prime
});
oldrx = newrx;
}
}
等效的 Go 代码:
func main() {
channel := make(chan int)
var ok bool = true;
var prime int = 0;
go generate(channel, 103)
for true {
prime, ok = <- channel
if !ok {
break;
}
new_channel := make(chan int)
go sieve(channel, new, prime)
channel = new_channel
fmt.Println(prime)
}
}
处理这种 Receiver
需要移交给不同线程的情况的最佳方法是什么?
你并没有真正解释你遇到的问题是什么,但你的代码已经足够接近了:
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
fn generate_numbers(tx: Sender<u8>) {
for i in 2..100 {
tx.send(i).unwrap();
}
}
fn filter(rx: Receiver<u8>, tx: Sender<u8>, val: u8) {
for v in rx {
if v % val != 0 {
tx.send(v).unwrap();
}
}
}
fn main() {
let (base_tx, base_rx) = channel();
thread::spawn(move || {
generate_numbers(base_tx);
});
let mut old_rx = base_rx;
loop {
let num = match old_rx.recv() {
Ok(v) => v,
Err(_) => break,
};
println!("prime: {}", num);
let (new_tx, new_rx) = channel();
thread::spawn(move || {
filter(old_rx, new_tx, num);
});
old_rx = new_rx;
}
}
using coroutines
危险,危险,Will Robinson!这些不是协程;他们是成熟的线程!与协程相比,这些更重量级。
What is the best way to deal with a situation like this where a Receiver
needs to be handed off to a different thread?
只是...将 Receiver
的所有权转移给线程?
我正在尝试使用协同程序在 Rust 中实现埃拉托色尼筛法作为学习练习(不是家庭作业),但我找不到任何合理的方法将每个线程连接到 Receiver
和 Sender
两个不同频道的末端。
Receiver
涉及两个不同的任务,即报告目前发现的最高素数,以及为过滤器提供更多候选素数。这是算法的基础。
这是我想做但做不到的,因为接收器不能在线程之间传输。不出所料,使用 std::sync::Arc
似乎没有帮助。
请注意,我明白为什么这不起作用
fn main() {
let (basetx, baserx): (Sender<u32>, Receiver<u32>) = channel();
let max_number = 103;
thread::spawn(move|| {
generate_natural_numbers(&basetx, max_number);
});
let oldrx = &baserx;
loop {
// we need the prime in this thread
let prime = match oldrx.recv() {
Ok(num) => num,
Err(_) => { break; 0 }
};
println!("{}",prime);
// create (newtx, newrx) in a deliberately unspecified way
// now we need to pass the receiver off to the sieve thread
thread::spawn(move || {
sieve(oldrx, newtx, prime); // forwards numbers if not divisible by prime
});
oldrx = newrx;
}
}
等效的 Go 代码:
func main() {
channel := make(chan int)
var ok bool = true;
var prime int = 0;
go generate(channel, 103)
for true {
prime, ok = <- channel
if !ok {
break;
}
new_channel := make(chan int)
go sieve(channel, new, prime)
channel = new_channel
fmt.Println(prime)
}
}
处理这种 Receiver
需要移交给不同线程的情况的最佳方法是什么?
你并没有真正解释你遇到的问题是什么,但你的代码已经足够接近了:
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
fn generate_numbers(tx: Sender<u8>) {
for i in 2..100 {
tx.send(i).unwrap();
}
}
fn filter(rx: Receiver<u8>, tx: Sender<u8>, val: u8) {
for v in rx {
if v % val != 0 {
tx.send(v).unwrap();
}
}
}
fn main() {
let (base_tx, base_rx) = channel();
thread::spawn(move || {
generate_numbers(base_tx);
});
let mut old_rx = base_rx;
loop {
let num = match old_rx.recv() {
Ok(v) => v,
Err(_) => break,
};
println!("prime: {}", num);
let (new_tx, new_rx) = channel();
thread::spawn(move || {
filter(old_rx, new_tx, num);
});
old_rx = new_rx;
}
}
using coroutines
危险,危险,Will Robinson!这些不是协程;他们是成熟的线程!与协程相比,这些更重量级。
What is the best way to deal with a situation like this where a
Receiver
needs to be handed off to a different thread?
只是...将 Receiver
的所有权转移给线程?