Swift标准库中的很多类型都已经实现了Sendable
接口。对于值类型(例如基础数据类型,数组,字典等)来说,它们天然是线程安全的,因为它们在使用过程中都是复制传值的。因此,它们在标准库中被默认实现为Sendable
。
例如,Swift中的Int
、Double
、Bool
、String
等基础类型以及它们组成的Array
、Dictionary
等集合类型都已经实现了Sendable
协议。
此外,对于我们自定义的值类型,例如结构体和枚举,只要它们的所有属性都遵循Sendable
协议,那么编译器会自动为我们的类型推导出Sendable
的遵循。
让我们来看一个例子:
// 这是一个简单的值类型结构体 struct Article { var title: String // String遵循了Sendable协议 var authors: [String] // String遵循了Sendable协议,所以[String]也遵循了Sendable协议 var readCount: Int // Int遵循了Sendable协议 } // Article自动遵循了Sendable协议,因为它的所有属性都遵循了Sendable协议 let article = Article(title: "Title", authors: ["Author1", "Author2"], readCount: 100) // 因此,我们可以在并发环境中安全地使用Article asyncDetached { print(article.title) }
Actor 是 Swift 5.5 中引入的新特性,它是一个引用类型,具有自己的内存管理和并发控制机制。Actor 的主要功能是确保并发访问时的线程安全。
Actor 的主要设计原则是“数据隔离”。Actor 内部的状态是私有的,只能通过 Actor 的方法进行访问,并且这些方法在调用时会自动进行调度,确保每次只有一个任务在访问 Actor 的内部状态,避免了数据竞争的问题。
下面是一个简单的 Actor 使用示例:
// 声明一个 Actor 类型 actor Counter { private var value = 0 // Actor内部的状态是私有的 // 提供一个方法用于修改内部状态 func increment() { value += 1 } // 提供一个方法用于获取内部状态 func get() -> Int { return value } } // 创建一个 Counter 的实例 let counter = Counter() // 在并发环境中使用 Counter Task { // 调用 Actor 的方法会自动进行调度,确保线程安全 await counter.increment() print(await counter.get()) // 输出:1 }
在这个例子中,我们创建了一个 Counter
类型的 actor,并在并发环境中对它
进行操作。由于 actor 会自动进行调度,我们可以确保 increment
和 get
方法不会同时被多个任务访问,从而避免了数据竞争的问题。
在Swift中,@Sendable
属性和Sendable
协议是两个不同但相互关联的概念,它们都是为了支持Swift的并发模型而设计的。
Sendable
协议是用于标识一个类型是否可以安全地在并发上下文中传递。例如,Swift的大多数值类型(如Int
,String
等)都是Sendable
的,因为它们是不可变的。然而,类类型(引用类型)需要额外的考虑,因为如果一个类的实例被多个线程共享并修改,可能会产生线程不安全的问题。如果你能保证你的类类型是线程安全的,你可以让它遵循Sendable
协议。
@Sendable
属性用于修饰函数或者闭包,它用来确保函数或闭包内部引用的所有对象都是Sendable
的,也就是可以安全地在并发上下文中传递。这对于写并发代码非常重要,因为你不想在你的函数或闭包内部有任何线程不安全的操作。
以下是一个@Sendable
属性的使用示例:
actor MyActor { var safeArray: [Int] = [] func appendValue(_ value: Int, completion: @Sendable () -> Void) { safeArray.append(value) completion() } }
在这个例子中,我们创建了一个actor,它有一个安全的数组safeArray
,我们提供了一个appendValue(_:completion:)
函数,它接受一个整数值和一个@Sendable
的闭包作为参数。因为这个闭包被标记为@Sendable
,所以我们可以保证在闭包中没有任何线程不安全的操作。
总的来说,Sendable
协议和@Sendable
属性都是Swift并发模型的一部分,它们帮助开发者编写更安全的并发代码。