数据在dispatch_barrier_sync上损坏

时间:2016-05-04 12:06:00

标签: arrays swift grand-central-dispatch nsdata

我有2个将数据附加到Array的函数和一个处理它的函数。我使用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显示内存地址而不是字节长度

干杯

2 个答案:

答案 0 :(得分:2)

You can't apply a barrier to a global queue:

  

您指定的队列应该是您使用dispatch_queue_create函数自己创建的并发队列。如果传递给此函数的队列是串行队列或全局并发队列之一,则此函数的行为类似于dispatch_sync函数。

答案 1 :(得分:1)

添加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) {

}

与你的问题的评论相关,我个人喜欢早期的回归模式,并防止自我消失:

someBlock { [weak self] () -> Void in

    guard let strongSelf = self else {
    return 
    }
}