Swift COW 线程安全
Posted
技术标签:
【中文标题】Swift COW 线程安全【英文标题】:Swift COW thread safety 【发布时间】:2017-12-13 21:52:58 【问题描述】:我正在研究写时复制在 swift 中的工作方式。 isKnownUniquelyReferenced
documentation 有点困惑。特别是本节:
如果作为对象传递的实例同时被多个线程访问,该函数可能仍然返回 true。因此,您只能从具有适当线程同步的变异方法中调用此函数。这将确保 isKnownUniquelyReferenced(_:) 仅在确实有一个访问器或存在竞争条件时才返回 true,这已经是未定义的行为。
所以想象一下。
-
我们有内部没有同步的 COW 结构。
拥有此结构实例并用锁保护它的类
此结构的吸气剂
并希望安全地从此 getter 线程返回副本
import Foundation
class StorageBuffer
var field: Int = 1
init(_ field: Int)
self.field = field
func copy() -> StorageBuffer
return StorageBuffer(field)
struct Storage
private var _buffer = StorageBuffer(1)
var field: Int
get
return _buffer.field
set
if !isKnownUniquelyReferenced(&_buffer)
_buffer = _buffer.copy()
_buffer.field = newValue
class StorageAware
private var _storage = Storage()
private let _storageGuard = NSLock()
var storage: Storage
_storageGuard.lock()
defer
_storageGuard.unlock()
return _storage
因为真正的复制将在以后发生。同步getter就够了吗?在这种情况下,是否有必要或结构本身是线程安全的? 是否有任何关于 swift 线程安全的完整文档?
【问题讨论】:
【参考方案1】:CoW 结构与Int
一样是线程安全的,即它们不是原子的。因此,就像您在修改 Int 时必须锁定并发访问一样,例如
lock.lock()
var myInt = _storedInt // lock required, not an atomic op
lock.unlock()
myInt += 1
您必须在复制 CoW 结构时执行相同的操作(您不会显示您的_storage
本身是否被修改过,尽管它被标记为var
,所以这表明它是 - 您需要锁定对_storage
的写访问)。
但是,当您这样做时,isKnownUniquelyReferenced
保证如果引用是唯一的,则返回 true。
错误:
var myStorage = _storage // this can race
myStorage.value = 10
对:
lock()
var myStorage = _storage // properly locked, can't race
unlock()
myStorage.value = 10 // this is safe now
错误的版本显示了文档所谈论的种族。
【讨论】:
以上是关于Swift COW 线程安全的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 分派到主队列是不是足以使 var 线程安全?