代码之家  ›  专栏  ›  技术社区  ›  pm100

将通道接收器交给派生线程

  •  1
  • pm100  · 技术社区  · 6 年前

    我有一个结构 Arc<Receiver<f32>> 我正在尝试添加一个方法来获取 self ,并将所有权移到新线程中并启动它。但是,我得到了一个错误

    error[E0277]: the trait bound `std::sync::mpsc::Receiver<f32>: std::marker::Sync` is not satisfied
      --> src/main.rs:19:9
       |
    19 |         thread::spawn(move || {
       |         ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<f32>` cannot be shared between threads safely
       |
       = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<f32>`
       = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::mpsc::Receiver<f32>>`
       = note: required because it appears within the type `Foo`
       = note: required because it appears within the type `[closure@src/main.rs:19:23: 22:10 self:Foo]`
       = note: required by `std::thread::spawn`
    

    Arc<i32> 相反,或者只是 Receiver<f32> 弧<接收器<f32>&燃气轮机;

    以下是完整代码:

    use std::sync::mpsc::{channel, Receiver, Sender};
    use std::sync::Arc;
    use std::thread;
    
    pub struct Foo {
        receiver: Arc<Receiver<f32>>,
    }
    
    impl Foo {
        pub fn new() -> (Foo, Sender<f32>) {
            let (sender, receiver) = channel::<f32>();
            let sink = Foo {
                receiver: Arc::new(receiver),
            };
            (sink, sender)
        }
    
        pub fn run_thread(self) -> thread::JoinHandle<()> {
            thread::spawn(move || {
                println!("Thread spawned by 'run_thread'");
                self.run(); // <- This line gives the error
            })
        }
    
        fn run(mut self) {
            println!("Executing 'run'")
        }
    }
    
    fn main() {
        let (example, sender) = Foo::new();
        let handle = example.run_thread();
        handle.join();
    }
    
    0 回复  |  直到 8 年前
        1
  •  6
  •   Shepmaster Tim Diekmann    8 年前

    这是怎么回事?

    thread::spawn 再一次:

    pub fn spawn<F, T>(f: F) -> JoinHandle<T> 
    where
        F: FnOnce() -> T,
        F: Send + 'static,   // <-- this line is important for us
        T: Send + 'static, 
    

    Foo 包含 Arc<Receiver<_>> ,让我们检查一下 Arc implements Send :

    impl<T> Send for Arc<T> 
    where
        T: Send + Sync + ?Sized,
    

    所以呢 Arc<T> 工具 如果 T 工具 Sync Receiver implements Send , it does not implement Sync .

    那为什么呢 有如此强烈的要求 T 发送 可以像容器一样工作;如果你能隐藏一些无法实现的东西 ,将它发送到另一个线程并在那里解包。。。坏事就会发生。有趣的是要知道原因 也必须实施 同步 ,这显然也是你正在努力解决的问题:

    编译器不能知道 在里面 #[derive(Clone)] 稍后(这是可能的,没有问题):

    fn main() {
        let (example, sender) = Foo::new();
        let clone = example.clone();
        let handle = example.run_thread();
        clone.run();
        // oopsie, now the same `Receiver` is used from two threads!
    
        handle.join();
    }
    

    接收器 在线程之间共享。这不好,因为 接收器 不执行 !

    对我来说,这个代码提出了一个问题:为什么 是唯一的所有者 . 如果你“不想分享(接收者)”,那么拥有多个所有者是没有意义的。

    推荐文章