Rust mpsc::Sender cannot be shared between threads?

半腔热情 提交于 2021-01-13 09:21:48

问题


I thought the whole purpose of a channel was to share data between threads. I have this code, based on this example:

let tx_thread = tx.clone();
let ctx = self;
thread::spawn(|| {
    ...
    let result = ctx.method()
    tx_thread.send((String::from(result), someOtherString)).unwrap();
})

Where tx is a mpsc::Sender<(String, String)>

error[E0277]: the trait bound `std::sync::mpsc::Sender<(std::string::String, std::string::String)>: std::marker::Sync` is not satisfied
   --> src/my_module/my_file.rs:137:9
    |
137 |         thread::spawn(|| {
    |         ^^^^^^^^^^^^^
    |
    = note: `std::sync::mpsc::Sender<(std::string::String, std::string::String)>` cannot be shared between threads safely
    = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<(std::string::String, std::string::String)>`
    = note: required because it appears within the type `[closure@src/my_module/my_file.rs:137:23: 153:10 res:&&str, ctx:&&my_module::my_submodule::Reader, tx_thread:&std::sync::mpsc::Sender<(std::string::String, std::string::String)>]`
    = note: required by `std::thread::spawn`

I'm confused where I went wrong. Unless I'm looking in the wrong place and my issue is actually my use of let ctx = self;?


回答1:


Sender cannot be shared between threads, but it can be sent!

It implements the trait Send but not Sync (Sync: Safe to access shared reference to Sender across threads).

The design of channels intends that you .clone() the sender and pass it as a value to a thread (for each thread you have). You are missing the move keyword on the thread's closure, which instructs the closure to capture variables by taking ownership of them.

If you must share a single channel endpoint between several threads, it must be wrapped in a mutex. Mutex<Sender<T>> is Sync + Send where T: Send.

Interesting implementation note: The channel starts out for use as a stream where it has a single producer. The internal data structures are upgraded to a multi-producer implementation the first time a sender is cloned.




回答2:


You may use std::sync::mpsc::SyncSender from the standard library. The diffrenece is that it implements the Sync trait but it will may block if there is no space in the internal buffer while sending a message.

For more information:

  • std::sync::mpsc::channel
  • std::sync::mpsc::sync_channel


来源:https://stackoverflow.com/questions/40384274/rust-mpscsender-cannot-be-shared-between-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!