You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动含Arc的self到新线程时为何出现“Sync未满足”错误?

Hey there! Let's break down why you're hitting this error and how to fix it.

First, the root cause: std::sync::mpsc::Receiver<f32> doesn't implement the Sync trait. Here's why that matters: when you wrap something in Arc<T>, Rust requires that T is both Send (can be moved to another thread) and Sync (can be safely shared across threads). The mpsc Receiver is Send (you can move it to a single thread), but it's not Sync because it's designed to be used by exactly one thread at a time—sharing it across threads would lead to race conditions and undefined behavior.

When you try to pass your Arc<Receiver<f32>> into thread::spawn, the compiler checks that the closure is Send (since it has to move to the new thread). But since Arc<Receiver<f32>> isn't Send (because Receiver isn't Sync), you get that E0277 error.

Now let's look at two solutions depending on your use case:

Solution 1: Ditch Arc (for single-threaded receiving)

If you only need one thread to handle receiving messages, you don't need Arc at all. The Receiver itself is Send, so you can just move it directly into the thread:

use std::sync::mpsc;
use std::thread;

struct MyStruct {
    receiver: mpsc::Receiver<f32>,
}

impl MyStruct {
    fn start_thread(self) {
        thread::spawn(move || {
            // Keep receiving until the sender is dropped
            while let Ok(value) = self.receiver.recv() {
                println!("Got value: {}", value);
            }
            println!("Receiver closed, exiting thread");
        });
    }
}

fn main() {
    let (sender, receiver) = mpsc::channel();
    let my_struct = MyStruct { receiver };
    
    // Start the thread
    my_struct.start_thread();
    
    // Send some test values
    sender.send(3.14).unwrap();
    sender.send(2.71).unwrap();
    
    // Drop the sender to close the channel
    drop(sender);
    
    // Wait a bit for the thread to finish (in real code, use a JoinHandle)
    thread::sleep(std::time::Duration::from_secs(1));
}

This works because we're transferring full ownership of the Receiver to the new thread—no sharing, so no need for Arc or Sync.

Solution 2: Use a thread-safe multi-consumer channel (for multi-threaded receiving)

If you need multiple threads to receive messages, the standard mpsc channel won't cut it (since it's single-consumer). Instead, use a channel that supports safe sharing across threads, like the ones from crossbeam-channel:

First, add the dependency to your Cargo.toml:

[dependencies]
crossbeam-channel = "0.5"

Then adjust your code:

use crossbeam_channel as channel;
use std::sync::Arc;
use std::thread;

struct MyStruct {
    receiver: Arc<channel::Receiver<f32>>,
}

impl MyStruct {
    fn start_thread(self) {
        // Clone the Arc for the first thread
        let receiver_clone = self.receiver.clone();
        thread::spawn(move || {
            while let Ok(value) = receiver_clone.recv() {
                println!("Thread 1 got: {}", value);
            }
        });
        
        // Use the original Arc for a second thread
        thread::spawn(move || {
            while let Ok(value) = self.receiver.recv() {
                println!("Thread 2 got: {}", value);
            }
        });
    }
}

fn main() {
    let (sender, receiver) = channel::unbounded();
    let my_struct = MyStruct { receiver: Arc::new(receiver) };
    
    my_struct.start_thread();
    
    sender.send(1.0).unwrap();
    sender.send(2.0).unwrap();
    drop(sender);
    
    thread::sleep(std::time::Duration::from_secs(1));
}

The crossbeam-channel::Receiver implements both Send and Sync, so wrapping it in Arc is safe. This lets multiple threads receive messages (note that each message goes to only one thread, like a queue—if you need broadcast, use channel::broadcast instead).

To recap:

  • Use plain Receiver without Arc if you only need one receiving thread
  • Use a multi-consumer channel like crossbeam-channel if you need multiple threads to receive

内容的提问来源于stack exchange,提问作者André T.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:49:57