“不要通过共享内存来通信,而要通过通信来共享内存。”通道到底怎么工作?send 后原变量还能用吗?什么时候 recv 会结束?值有没有被复制?这篇把通道最基本的行为逐条验证。
编译:成功
运行(退出码 0):
recv 阻塞了 100 毫秒(取整到 50),收到 "来自子线程"
源码:
1 | use std::sync::mpsc;
2 | fn main() { let (tx, rx) = mpsc::channel(); let s = String::from("x"); tx.send(s).unwrap(); println!("{}", s); let _ = rx; }
编译:失败
error[E0382]: borrow of moved value: `s`
--> <实验目录>/src/u88b.rs:2:108
|
2 | fn main() { let (tx, rx) = mpsc::channel(); let s = String::from("x"); tx.send(s).unwrap(); println!("{}", s); let _ = rx; }
| - - ^ value borrowed here after move
| | |
| | value moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
|
help: consider cloning the value if the performance cost is acceptable
|
2 | fn main() { let (tx, rx) = mpsc::channel(); let s = String::from("x"); tx.send(s.clone()).unwrap(); println!("{}", s); let _ = rx; }
| ++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0382`. 编译:成功
运行(退出码 0):
子线程结束,tx 随之 drop
for / iter 收完后结束,共收到 [1, 2, 3]
再 recv: Err(RecvError) 编译:成功
运行(退出码 0):
空通道 try_recv: Err(Empty)
recv_timeout(50ms): Err(Timeout)
有值时 try_recv: Ok(1)
发送端都 drop 后 try_recv: Err(Disconnected)
发送端都 drop 后 recv_timeout: Err(Disconnected) 编译:成功
运行(退出码 0):
send 失败: sending on a closed channel 被退回的值: "没人收" 源码:
1 | use std::{sync::mpsc, rc::Rc, thread};
2 | fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { tx.send(Rc::new(1)).unwrap(); }); let _ = rx.recv(); }
编译:失败
error[E0277]: `Rc<i32>` cannot be sent between threads safely
--> <实验目录>/src/u88f.rs:2:59
|
2 | fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { tx.send(Rc::new(1)).unwrap(); }); let _ = rx.recv(); }
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<i32>` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `Rc<i32>`
= note: required for `std::sync::mpsc::Sender<Rc<i32>>` to implement `Send`
note: required because it's used within this closure
--> <实验目录>/src/u88f.rs:2:59
|
2 | fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { tx.send(Rc::new(1)).unwrap(); }); let _ = rx.recv(); }
| ^^^^^^^
note: required by a bound in `spawn`
--> <rust 标准库源码>/library/std/src/thread/functions.rs:128:8
|
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
| ----- required by a bound in this function
...
128 | F: Send + 'static,
| ^^^^ required by this bound in `spawn`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.Send 的规则见Send 与 Sync。
编译:成功
运行(退出码 0):
发送前缓冲区地址 == 接收后缓冲区地址: true(100 万个 u64 没有被复制)多个生产者的情形见mpsc 多生产者单消费者。