【问题标题】:Cannot Send A Struct Across Threads which has mpsc::Sender as field无法跨具有 mpsc::Sender 作为字段的线程发送结构
【发布时间】:2020-12-18 17:29:31
【问题描述】:

我有一个结构体,其字段为 Sender

pub struct GenericConnectionPool<E>
where
    E: ConnectionConnector,
{
    _sender: Sender<()>,
    _reciever: Arc<Mutex<Receiver<()>>>,
    _num_of_live_connections: AtomicU8,
    _max_connections: u8,
    _min_connections: u8,
    _connections: Arc<Mutex<Vec<<E as ConnectionConnector>::Conn>>>,
    _connector: E,
}

我在多个线程中使用该结构,这就是为什么在 Arc 中使用它并克隆它的原因。

let pool = Arc::new(GenericConnectionPool::new(2, 1, cc));
println!("here");
{
    for _ in 0..3 {
        let pool = Arc::clone(&pool);
        std::thread::spawn(move || {
            pool.get_connection();
            thread::sleep(Duration::from_secs(1));
        });
    }
}

但我收到了我的结构无法跨线程发送的错误。

`std::sync::mpsc::Sender<()>` cannot be shared between threads safely
within `GenericConnectionPool<tests::connector_works::DummyConnectionConnector>`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>`
required because it appears within the type `GenericConnectionPool<tests::connector_works::DummyConnectionConnector>`
required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<GenericConnectionPool<tests::connector_works::DummyConnectionConnector>>`
required because it appears within the type `[closure@src/lib.rs:169:36: 172:18 pool:std::sync::Arc<GenericConnectionPool<tests::connector_works::DummyConnectionConnector>>]`

我的理解是Sender类型不能安全地跨线程发送,但是由于它的cloneable,你可以克隆它然后跨线程发送。但在我的情况下,发件人在我的结构中。我想不出办法来解决这个问题。

我想我可能不得不改变我的设计。

【问题讨论】:

标签: multithreading rust


【解决方案1】:

你可以使用横梁。它的crossbeam::Sender 似乎可以在线程之间转移。大概,你也需要使用它的crossbeam::Receiver

或者,您可以将 GenericConnectionPool 重构为如下所示:

pub struct ExtraData {}

#[derive(Clone)]
pub struct GenericConnectionPool {
    _sender: Sender<()>,
    _extra_data: Arc<ExtraData>,
}

那么您可以直接克隆 GenericConnectionPool 而不是包含它的 Arc 并获得正确的行为:

let pool = GenericConnectionPool{_sender:s, _extra_data:Arc::new(ExtraData{}) };

for _ in 0..3 {
   let pool = pool.clone();
   std::thread::spawn(move || {
       pool.get_connection();
       thread::sleep(Duration::from_secs(1));
    });
}

可以看到编译版本here

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
相关资源
最近更新 更多