it编程 > 编程语言 > rust

深入理解Rust中的 Send 和 Sync trait

46人参与 2025-11-24 rust

rust中的标记 trait(marker trait)sendsync 是并发安全的核心基石。用于标记类型的并发安全属性,让编译器在编译时检查线程间数据传递的合法性,从根源上避免数据竞争(data race)。

send

一个类型 tsend,表示把 t 的一个 值 从一个线程移动到另一个线程,不会引发数据竞争或内存安全问题。

绝大多数类型自动实现 send,以下一些例外(!send):

use std::thread;
fn main() {
    let v = vec![1, 2, 3];
    // vec<i32> 是 send,通过move把所有权移到线程中
    let handle = thread::spawn(move || {
        println!("{:?}", v);
    });
    handle.join().unwrap();
}

sync

一个类型 tsync,表示可以安全地被多个线程共享(即 &tsend)。即,如果一个类型的引用 &t 能安全跨线程传递,那么这个类型就是 sync(多个线程持有 &t 不会导致数据竞争)。

任何允许通过 共享引用 &t 获得可变访问 且没有同步保护的类型,都不是 sync

use std::sync::{arc, mutex};
use std::thread;
fn main() {
    let data = arc::new(mutex::new(5)); // arc<mutex<i32>>
    let data_clone = data.clone();
    thread::spawn(move || {
        let mut guard = data_clone.lock().unwrap(); // 加锁,独占访问
        *guard += 1;
    }).join().unwrap();
    println!("{}", data.lock().unwrap()); // 输出 6
}

auto trait

sendsync 都是 auto trait,编译器会根据类型的组成部分自动推导实现。

性质含义常见例子
send + sync可以在线程间移动,也可以多线程共享引用i32, mutex<t>
send + !sync可以在线程间移动,但不能多线程共享引用一些 *mut t封装,sender<t>
!send + sync不能跨线程移动;不移动,只读共享是安全的(较少见)少数特殊 ffi 对象
!send + !sync既不能跨线程移动,也不能多线程共享引用rc<refcell<t>>

只有在特殊情况下(写 底层库 / ffi 封装 / 自己的锁和原子数据结构 时)才会需要手动实现sendsync

use std::sync::mutex;
// 自定义类型:用 mutex 保护裸指针(裸指针本身 !send/!sync)
struct safeptr<t>(mutex<*mut t>);
impl<t> safeptr<t> {
    fn new(value: t) -> self {
        let ptr = box::into_raw(box::new(value)); // 裸指针指向堆内存
        safeptr(mutex::new(ptr))
    }
    // 安全访问:通过 mutex 加锁,保证独占访问
    fn get(&self) -> option<&t> {
        let guard = self.0.lock().ok()?;
        unsafe { (*guard).as_ref() } // 裸指针解引用需 unsafe,但锁保证安全
    }
}
// 手动实现 send/sync:因为内部用 mutex 保护,访问裸指针是线程安全的
unsafe impl<t> send for safeptr<t> {}
unsafe impl<t> sync for safeptr<t> {}
// 测试:跨线程共享 safeptr
fn main() {
    let ptr = safeptr::new(5);
    let ptr_clone = arc::new(ptr);
    let ptr_clone2 = ptr_clone.clone();
    thread::spawn(move || {
        println!("线程内访问:{}", ptr_clone2.get().unwrap()); // 安全
    }).join().unwrap();
}

到此这篇关于深入理解rust中的 send 和 sync trait的文章就介绍到这了,更多相关rust send 和 sync trait内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

Rust 中引用模式与值模式的对比实践指南

11-04

Rust使用Trait对象实现多态的详细步骤

11-03

Rust 智能指针的使用详解

09-24

使用Rust语言搞定图片上传功能的示例详解

08-03

Rust 函数式编程的具体使用

06-27

Rust 中的时间处理利器chrono示例详解

06-27

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论