- Published on
 
Send与Sync:代码示例
1. Basic Send Example: Moving Data Between Threads
use std::thread;
fn main() {
    let data = vec![1, 2, 3]; // Vec<i32> is Send + Sync
    
    let handle = thread::spawn(move || {
        println!("Data in thread: {:?}", data); // Ownership moved here
    });
    
    handle.join().unwrap();
}
Key Point: Vec<i32> implements Send, so its ownership can be transferred across threads.
2. Sync Example: Shared Immutable Data with Arc
use std::sync::Arc;
use std::thread;
fn main() {
    let shared_data = Arc::new(42); // Arc<T> requires T: Send + Sync
    
    let handles: Vec<_> = (0..3).map(|_| {
        let data = Arc::clone(&shared_data);
        thread::spawn(move || {
            println!("Thread sees: {}", data); // Shared immutable reference
        })
    }).collect();
    for h in handles {
        h.join().unwrap();
    }
}
Key Point: Arc<T> allows shared read-only access across threads (Sync behavior).
3. Thread-Safe Mutability with Mutex (Send + Sync)
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
    let counter = Arc::new(Mutex::new(0)); // Mutex<T> requires T: Send
    
    let handles: Vec<_> = (0..10).map(|_| {
        let counter = Arc::clone(&counter);
        thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1; // Safe mutable access
        })
    }).collect();
    for h in handles {
        h.join().unwrap();
    }
    
    println!("Result: {}", *counter.lock().unwrap());
}
Key Points:
Mutex<T>implementsSyncwhenT: SendArc<Mutex<T>>is a classic thread-safe interior mutability pattern
4. Non-Send Type Example (Rc)
use std::rc::Rc;
use std::thread;
fn main() {
    let data = Rc::new(42);
    
    // This would fail to compile:
    // thread::spawn(move || {
    //     println!("{}", data); // ERROR: Rc<i32> cannot be sent between threads
    // });
}
Fix: Replace Rc with Arc to make it Send.
5. Custom Send + Sync Implementation (Advanced)
use std::marker::PhantomData;
struct MyThreadSafePtr<T: Send>(*const T);
// SAFETY: We guarantee pointer access is synchronized externally
unsafe impl<T: Send> Send for MyThreadSafePtr<T> {}
unsafe impl<T: Send> Sync for MyThreadSafePtr<T> {}
fn main() {
    let val = 10;
    let ptr = MyThreadSafePtr(&val as *const i32);
    
    thread::spawn(move || {
        // Can move to thread because we implemented Send
        println!("Pointer in thread: {:p}", ptr.0);
    }).join().unwrap();
}
Key Points:
- Manual 
unsafe implrequires careful safety guarantees PhantomDataoften used for generic types
6. Conditional Send/Sync with Generic Types
use std::marker::PhantomData;
struct Container<T> {
    data: T,
    _marker: PhantomData<*const ()>, // Affects auto-traits
}
// Only Send when T is Send
unsafe impl<T: Send> Send for Container<T> {}
// Only Sync when T is Sync
unsafe impl<T: Sync> Sync for Container<T> {}
fn main() {
    let container = Container {
        data: 42,
        _marker: PhantomData,
    };
    
    thread::spawn(move || {
        println!("{}", container.data); // Works because i32 is Send
    }).join().unwrap();
}
7. Channel Communication (Send in Action)
use std::sync::mpsc;
use std::thread;
fn main() {
    let (tx, rx) = mpsc::channel();
    
    thread::spawn(move || {
        let data = vec![1, 2, 3];
        tx.send(data).unwrap(); // Moving ownership through channel
    });
    
    println!("Received: {:?}", rx.recv().unwrap());
}
Key Point: Channels require their contents to implement Send.
8. Parallel Processing with Rayon (Sync Showcase)
use rayon::prelude::*;
fn main() {
    let data = vec![1, 2, 3, 4, 5];
    
    let sum: i32 = data.par_iter() // Requires &[T] where T: Sync
        .map(|x| x * 2)
        .sum();
    
    println!("Parallel sum: {}", sum);
}
Key Takeaways:
Sendenables ownership transfer between threadsSyncenables shared references (&T) across threads- Most Rust types are 
Send/Syncby default - Composition matters - compound types inherit 
Send/Syncfrom components - Thread-safe patterns combine 
Arc(Sync) withMutex/RwLock(Send) 
THE END