Sendable 协议-Swift 结构化并发的核心安全保障

Sendable 是 Swift 5.5+ 为并发安全 设计的标记协议,核心作用是:告诉编译器「这个类型的实例可以安全地跨 Task/线程传递」,不会引发数据竞争。

一、核心本质

  1. Sendable 是「空协议」(无需要实现的方法),仅作为编译期检查标记,不影响运行时性能;
  2. 遵循 Sendable 的类型,要么是「不可变的」(值类型+只读属性),要么是「线程安全的」(如加锁、Actor 封装)。

二、哪些类型默认遵循 Sendable?

无需手动声明,Swift 内置类型已默认遵循:

  • 基础值类型:Int/String/Bool/Double/Array(不可变)/Dictionary(不可变);
  • 原子类型:Atomic(Swift 5.9+);
  • 空元组:();
  • 不可变枚举:无关联值/关联值也遵循 Sendable 的枚举。

三、实用示例

1. 自定义类型遵循 Sendable

场景1:不可变值类型(直接遵循)
swift 复制代码
// 所有属性都是 let(不可变),直接遵循 Sendable
struct User: Sendable {
    let id: Int
    let name: String
    let createTime: Date
}

// 跨 Task 传递:编译器判定安全
Task {
    let user = User(id: 1, name: "张三", createTime: Date())
    Task {
        print(user.name) // 无数据竞争风险
    }
}
场景2:可变类型(需保证线程安全)
swift 复制代码
import OSAtomic

// 可变类:通过原子操作保证线程安全后遵循 Sendable
final class Counter: Sendable {
    private var _count: Int32 = 0 // 原子整型
    
    // 原子操作读写,保证线程安全
    var count: Int {
        get { Int(OSAtomicAdd32(0, &_count)) }
        set { OSAtomicStore32(Int32(newValue), &_count) }
    }
}

2. 编译期安全检查(核心价值)

如果类型不遵循 Sendable 却跨 Task 传递,编译器会直接报错,提前拦截数据竞争风险:

swift 复制代码
// 未遵循 Sendable 的可变类型
struct UnsafeData {
    var value: String // 可变,无线程安全保障
}

// 编译报错:传递非 Sendable 类型存在数据竞争风险
Task {
    var data = UnsafeData(value: "test")
    Task {
        data.value = "error" // ❌ 编译器直接提示错误
    }
}

四、关键使用场景

  1. Task/Async Closure 传参:跨并发任务传递的数据必须遵循 Sendable;
  2. Actor 通信:Actor 之间传递的消息(参数/返回值)必须遵循 Sendable;
  3. 全局变量/缓存:并发场景下的全局数据,标记为 Sendable 保证安全;
  4. 闭包捕获:异步闭包中捕获的变量,编译器会检查是否遵循 Sendable。

五、常见坑点

  1. 可变容器 :var array: [Int] 是可变数组,不遵循 Sendable;let array: [Int](不可变)才遵循;
  2. 类类型:类默认不遵循 Sendable(即使属性是 let),需手动声明并保证线程安全;
  3. 嵌套类型:嵌套类型需也遵循 Sendable,外层类型才能遵循。

总结

  1. Sendable 是编译期并发安全标记,无实际方法需实现;
  2. 不可变值类型可直接遵循,可变类型需保证线程安全后遵循;
  3. 核心作用:由编译器提前拦截跨线程数据竞争风险,而非运行时处理;
  4. 是 Swift 结构化并发的核心安全保障,异步编程中必须关注。
相关推荐
Anhty2 小时前
2026最新免费手机音频处理工具 !!
android·功能测试·ios·智能手机·音视频
2501_915909064 小时前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
初雪云6 小时前
UniApp 云打包拿到 IPA 后,真正的发布工作才刚开始
ios·自动化·编辑器·产品经理·iphone
Lancker7 小时前
没有 Mac 也能上架 iOS:GitHub Actions 全自动构建 + 签名 + TestFlight 送审实录
macos·ios·github
茶底世界之下7 小时前
晚霞要多暖?用 Awaking 只改色温做一次取舍
ios
酒神dnspup9 小时前
多地区网站可用性监控怎么做?DNSPup 从基线到告警的完整实战
运维·ios·云计算·iphone·dns·网络监控
福兮说1 天前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
茶底世界之下1 天前
时间线效果层,为什么不能只复用一个处理器?
ios·swift
ZZH_AI项目交付1 天前
实时字幕负责快,本地录音负责不丢:一个 iOS 录音功能为什么需要两条链路
ios·ai编程
Cc.Y1 天前
Swift深度链接的极简之道
ios·cocoa·swift