测试已测试 | ✗ |
语言语言 | SwiftSwift |
许可证 | MIT |
发布上次发布 | 2016年10月 |
SPM支持 SPM | ✗ |
由 Honza Dvorsky 和 Dominik Hadl 维护。
线程同步变得容易。
性能敏感的类需要内部状态同步,以确保外部访问器不会破坏内部不变量和引起竞态条件。直接使用 GCD (Grand Central Dispatch) 可能会使新手困惑,因为 API 并不一定反映使用它的实际原因。这就是为什么将 Swifty API 封装进其中可以给您的代码带来一点清晰的解释。下面是示例。
让我们假设您正在编写一个线程安全的 NSData
缓存。您希望它使用 CREW 访问以最大化性能。
class MyCache {
private let storage: NSMutableDictionary = NSMutableDictionary()
public func hit(key: String) -> NSData? {
let found = self.storage[key]
if let found = found {
print("Hit for key \(key) -> \(found)")
} else {
print("Miss for key \(key)")
}
return found
}
public func update(key: String, value: NSData) {
print("Updating \(key) -> \(value)")
self.storage[key] = value
}
}
这是第一个实现。它有效,但当您同时从多个线程调用它时,您将遇到不一致和竞态条件——意味着您将获得相同操作序列的不同结果。在更复杂的情况下,您甚至可能引起运行时崩溃。
修复它的方式明显是通过保护内部 storage
(注意:NSDictionary
不是线程安全的)。同样,为了 Most 高效,您希望允许任何数量的线程从缓存中读取,但只允许一个线程更新它(并确保在此期间没有人正在读取它)。您可以使用 GCD 来实现这些保证,这正是 SwiftSafe 所做的。然而,此 API 带给桌面的是简单而明显的命名。
让我们看看我们如何在几行代码中将我们的缓存线程安全化。
import SwiftSafe
class MyCache {
private let storage: NSMutableDictionary = NSMutableDictionary()
private let safe: Safe = CREW()
public func hit(key: String) -> NSData? {
var found: NSData?
safe.read {
found = self.storage[key]
if let found = found {
print("Hit for key \(key) -> \(found)")
} else {
print("Miss for key \(key)")
}
}
return found
}
public func update(key: String, value: NSData) {
safe.write {
print("Updating \(key) -> \(value)")
self.storage[key] = value
}
}
}
这就完成了!只需导入库,创建一个遵循你想要实现的并发模式(在本例中是CREW)的 Safe
对象,并将对共享资源的访问封装在 read
和 write
调用中。请注意,read
封闭调用总是 阻塞 调用线程,而 write
则不会。如果你有一个同时更新你的资源并从它读取的调用,请确保将该功能分成 写入 和 读取 部分。这将使其推理和并行化变得更加容易。
虽然对一些人来说可能看起来没有必要,但可理解和正确的方法的同步会为你省去几天调试和许多烦恼。 :)
请注意,该项目以捐助者行为准则发布。通过参与此项目,你同意遵守其条款。
MIT
Honza Dvorsky - http://honzadvorsky.com,@czechboy0