DispatchQueue障碍问题
问题描述:
试图使线程安全的数组,但它的工作原理并不如我所料DispatchQueue障碍问题
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
public class SafeArray<Element> {
private var array = [Element]()
private let queue = DispatchQueue(label: "queueBarrier", attributes: .concurrent)
public func append(element: Element) {
queue.async(flags: .barrier) {
self.array.append(element)
}
}
public var elements: [Element] {
var result = [Element]()
queue.sync {
result = self.array
}
return result
}
public var last: Element? {
var result: Element?
queue.sync {
result = self.array.last
}
return result
}
}
var safeArray = SafeArray<Int>()
var array = Array<Int>()
DispatchQueue.concurrentPerform(iterations: 10) { (int) in
let last = array.last ?? 0
array.append(last + 1)
print("array = [..\(last)]")
}
print(array)
DispatchQueue.concurrentPerform(iterations: 10) { (int) in
let last = safeArray.last ?? 0
safeArray.append(element: last + 1)
print("safeArray = [..\(last)]")
}
print(safeArray.elements)
我预计阵列应该有一些混乱,但SAFEARRAY应该有一个数字从0到9
据我所知,array有3个值,但safeArray有10个值按预期。但为什么这个值不是从0到9?
谢谢!
答
不,你不会得到价值形态1 - 10 !!!,由于DispatchQueue.concurrentPerform
执行多个操作的同时
让我解释一下
假设DispatchQueue.concurrentPerform
将同时执行3项,然后这里
let last = safeArray.last ?? 0
你会得到0三次然而它是通过增加1其追加数组,以便
您的数组变得像[1,1,1 ...]
有巴里在这里输出的还是我没有清算角色
尽管屏障进程正在运行,但读者仍然会被阻止。即使有并行已经运行几个读者块,屏障进程将等待所有的读者开始写
如果您需要阻止行为,你应该使用DispatchSemaphore
为MjZac解释之前完成
希望你明白
答
为什么不使用DispatchSemaphore
?
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
public class SafeArray<Element> {
private var array = [Element]()
private let semaphore = DispatchSemaphore(value: 1)
private var lastEl: Element?
public func append(element: Element) {
self.array.append(element)
}
public var elements: [Element] {
var result = [Element]()
result = self.array
return result
}
public var last: Element? {
self.semaphore.wait()
lastEl = self.array.last
self.semaphore.signal()
return lastEl
}
}
var safeArray = SafeArray<Int>()
var array = Array<Int>()
DispatchQueue.concurrentPerform(iterations: 10) { (int) in
let last = array.last ?? 0
array.append(last + 1)
print("array = [..\(last)]")
}
print(array)
DispatchQueue.concurrentPerform(iterations: 10) { (int) in
let last = safeArray.last ?? 0
safeArray.append(element: last + 1)
print("safeArray = [..\(last)]")
}
print(safeArray.elements)