我想要执行一系列闭包,并以安全的方式删除每个项目。
如果我这样做:
array.forEach { $0() }
array.removeAll()
项目可能在forEach
和removeAll
执行之间偷偷摸摸,所以我可能会移除一个在前一行中没有执行的元素
这样的事情会更安全吗?
extension Array {
mutating func removeEach(handler: @escaping (Element) -> Void) {
enumerated().forEach { handler(remove(at: $0.offset)) }
}
}
有没有一种安全的方法以算法的方式执行此操作而不是使用线程锁?
答案 0 :(得分:5)
首先,我假设array
这里是一个属性(否则这个问题没有多大意义)。其次,我假设array
已经成为线程安全的。也许是这样的,它提供了阵列级别的同步访问。
class Container {
let arrayQueue = DispatchQueue(label: "arrayQueue", attributes: .concurrent)
var _array: [() -> Void] = []
var array: [() -> Void] {
get {
return arrayQueue.sync { return _array }
}
set {
arrayQueue.async(flags: .barrier) {
self._array = newValue
}
}
}
}
使用这种系统,你可以创建一个清除数组的原子执行器:
func execute() {
arrayQueue.async(flags: .barrier) {
// Make a local copy of the array
let toExecute = self._array
// Clear the array (we have a barrier, so there's no race condition)
self._array.removeAll()
// async to another queue to avoid blocking access while executing
DispatchQueue.global().async {
for closure in toExecute {
closure()
}
}
}
}
(你提到过#34;没有使用线程锁。"你几乎不应该在Swift中使用线程锁。这就是GCD的用途,它做了很多工作来避免锁定所以你不必这样做。如果你的目标是在不使用GCD的情况下这样做,那么不,没有某种并发系统就没有办法从多个线程安全地改变一个属性,并且最好的并发系统斯威夫特是GCD。)