[英]Parallel array elements assignment causes crash in Swift
我想同时设置数组的元素,所以我编写代码来测试:
let Count = 1000
let SubRangeCount = 100
var ary = [Int](repeating: 0, count: Count)
let times = Count/SubRangeCount
let _ = DispatchQueue.global(qos: .userInitiated)
DispatchQueue.concurrentPerform(iterations: times){ idx in
for i in (idx * SubRangeCount)..<((idx+1) * SubRangeCount) {
ary[i] = Int.random(in: 0...Int.max)
}
}
}
上面的代码工作得很好:但是当我这样改变时:
let Count = 10000
let SubRangeCount = 1000
它崩溃了:在操场上它抱怨“致命错误。UnsafeMutablePointer:初始化重叠范围。文件 Swift/UnsafePointer,swift,第 832 行”
但是您可以看到数组分配的每个范围都没有重叠!
那么如何解决呢? 谢谢!
Array
在 Swift 上不是线程安全的,因此您需要同步对它的访问,例如使用objc_sync_enter
和objc_sync_exit
:
func synchronized<T : AnyObject, U>(_ obj: T, closure: () -> U) -> U {
objc_sync_enter(obj)
defer {
objc_sync_exit(obj)
}
return closure()
}
var arr = [Int](repeating: 0, count: 100_000)
let obj = arr as NSObject // Object to synchronise
DispatchQueue.concurrentPerform(iterations: 100_000){ index in
synchronized(obj) {
arr[index] = Int.random(in: 0...Int.max)
}
}
这里数组是从多个线程同时变异的,这会产生竞争条件。 为避免这种情况,您必须以线程安全的方式执行关键操作。 您可以从 Apple 平台中的 Grand Central Dispatch 获得帮助——它让我们可以使用其更简单的基于队列的抽象来处理线程。
let Count = 10000
let SubRangeCount = 1000
var ary = [Int](repeating: 0, count: Count)
let times = Count/SubRangeCount
let serialQueue = DispatchQueue(label: "serial.Queue")
DispatchQueue.concurrentPerform(iterations: times){ idx in
print(idx)
for i in (idx * SubRangeCount)..<((idx+1) * SubRangeCount) {
serialQueue.async {
ary[i] = Int.random(in: 0...Int.max)
}
}
}
您也可以使用锁。
let Count = 10000
let SubRangeCount = 1000
var ary = [Int](repeating: 0, count: Count)
let lock = NSLock()
let times = Count/SubRangeCount
DispatchQueue.concurrentPerform(iterations: times){ idx in
print(idx)
for i in (idx * SubRangeCount)..<((idx+1) * SubRangeCount) {
lock.lock()
ary[i] = Int.random(in: 0...Int.max)
lock.unlock()
}
}
我找到了解决方法:
DispatchQueue.concurrentPerform(iterations: enumTimes){ idx in
var subAry = ary1[(idx * SubRangeCount)..<((idx+1) * SubRangeCount)]
for i in subAry.indices {
subAry[i] = Int.random(in: 0...Int.max)
}
}
它没有崩溃,并且比序列化作业快 3 到 10 倍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.