数组在 dispatch_barrier_sync 上损坏
Array corrupt on dispatch_barrier_sync
我有 2 个将数据附加到数组的函数和一个处理它的函数。我使用 dispatch_barrier_sync 来防止其他函数在我处理数据时更改数据。
内部追加函数:
autoreleasepool {
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self] () -> Void in
self?.bufferVector_.append(data)
}
}
内部处理函数:
autoreleasepool {
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self] in
let len = self!.bufferVector_.count
if len > numToExtract {
isMoreInBuffer = true
}
for bufferData in self!.bufferVector_ {
datas.append(bufferData)
cnt += 1
if cnt == numToExtract {
break;
}
}
self!.bufferVector_.removeRange(Range(start: 0, end: cnt))
}
}
在上面的函数中,bufferVector 是 NSData 数组 ( [NSData] )
该函数工作正常,过了一会儿,数组中的 NSData 似乎已损坏,我收到 EXC_BAD_ACCESS
这是我尝试从调试器查看 bufferVector 内容时显示的内容
bufferVector_ = ([NSData]) 8 values
[0] = (NSData) 98 bytes
[1] = (NSData) 0x16595320
[2] = (NSData) 52 bytes
[3] = (NSData) 52 bytes
我可以说它已损坏,因为 NSData 显示内存地址而不是字节长度
干杯
You can't apply a barrier to a global queue:
The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.
添加到 Rob 的回答中,您可以创建一个队列,您可以访问或传递给任一方法:
let qosClassUserInit = QOS_CLASS_USER_INITIATED
let newConcurrentQueueAttributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, qosClassUserInit, 0)
let newConcurrentQueue = dispatch_queue_create("SynchronizedArrayAccess", newConcurrentQueueAttributes)
然后像这样使用它:
// Getting elements
dispatch_sync(newConcurrentQueue) {
}
// Setting elements
dispatch_barrier_async(newConcurrentQueue) {
}
关于你的问题的评论,我个人喜欢早期的return模式和防止自我消失:
someBlock { [weak self] () -> Void in
guard let strongSelf = self else {
return
}
}
我有 2 个将数据附加到数组的函数和一个处理它的函数。我使用 dispatch_barrier_sync 来防止其他函数在我处理数据时更改数据。
内部追加函数:
autoreleasepool {
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self] () -> Void in
self?.bufferVector_.append(data)
}
}
内部处理函数:
autoreleasepool {
dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self] in
let len = self!.bufferVector_.count
if len > numToExtract {
isMoreInBuffer = true
}
for bufferData in self!.bufferVector_ {
datas.append(bufferData)
cnt += 1
if cnt == numToExtract {
break;
}
}
self!.bufferVector_.removeRange(Range(start: 0, end: cnt))
}
}
在上面的函数中,bufferVector 是 NSData 数组 ( [NSData] )
该函数工作正常,过了一会儿,数组中的 NSData 似乎已损坏,我收到 EXC_BAD_ACCESS
这是我尝试从调试器查看 bufferVector 内容时显示的内容
bufferVector_ = ([NSData]) 8 values
[0] = (NSData) 98 bytes
[1] = (NSData) 0x16595320
[2] = (NSData) 52 bytes
[3] = (NSData) 52 bytes
我可以说它已损坏,因为 NSData 显示内存地址而不是字节长度
干杯
You can't apply a barrier to a global queue:
The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.
添加到 Rob 的回答中,您可以创建一个队列,您可以访问或传递给任一方法:
let qosClassUserInit = QOS_CLASS_USER_INITIATED
let newConcurrentQueueAttributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, qosClassUserInit, 0)
let newConcurrentQueue = dispatch_queue_create("SynchronizedArrayAccess", newConcurrentQueueAttributes)
然后像这样使用它:
// Getting elements
dispatch_sync(newConcurrentQueue) {
}
// Setting elements
dispatch_barrier_async(newConcurrentQueue) {
}
关于你的问题的评论,我个人喜欢早期的return模式和防止自我消失:
someBlock { [weak self] () -> Void in
guard let strongSelf = self else {
return
}
}