And*_*rew 16 arrays multithreading read-write grand-central-dispatch swift
我想将给定的块添加到数组中,然后在请求时运行数组中包含的所有块.我有类似这样的代码:
class MyArrayBlockClass {
private var blocksArray: Array<() -> Void> = Array()
private let blocksQueue: NSOperationQueue()
func addBlockToArray(block: () -> Void) {
self.blocksArray.append(block)
}
func runBlocksInArray() {
for block in self.blocksArray {
let operation = NSBlockOperation(block: block)
self.blocksQueue.addOperation(operation)
}
self.blocksQueue.removeAll(keepCapacity: false)
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于可以跨多个线程调用addBlockToArray.发生的事情是addBlockToArray在不同的线程中快速连续调用,并且只附加其中一个项目,因此在runBlocksInArray期间不会调用另一个项目.
我尝试过这样的东西,但似乎不起作用:
private let blocksDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
func addBlockToArray(block: () -> Void) {
dispatch_async(blocksDispatchQueue) {
self.blocksArray.append(block)
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 26
您已将自己定义blocksDispatchQueue为全局队列.为Swift 3更新这个,相当于:
private let queue = DispatchQueue.global()
func addBlockToArray(block: @escaping () -> Void) {
queue.async {
self.blocksArray.append(block)
}
}
Run Code Online (Sandbox Code Playgroud)
问题是全局队列是并发队列,因此您无法实现所需的同步.但是如果你创建了自己的串行队列,那就好了,例如在Swift 3中:
private let queue = DispatchQueue(label: "com.domain.app.blocks")
Run Code Online (Sandbox Code Playgroud)
默认情况下,此自定义队列是串行队列.因此,您将实现所需的同步.
请注意,如果您使用此方法blocksDispatchQueue来同步与此队列的交互,则应通过此队列协调与此交互的所有交互blocksArray,例如,还要调度代码以使用相同的队列添加操作:
func runBlocksInArray() {
queue.async {
for block in self.blocksArray {
let operation = BlockOperation(block: block)
self.blocksQueue.addOperation(operation)
}
self.blocksArray.removeAll()
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以使用读取器/写入器模式,创建自己的并发队列:
private let queue = DispatchQueue(label: "com.domain.app.blocks", attributes: .concurrent)
Run Code Online (Sandbox Code Playgroud)
但是在读写器模式中,应该使用barrier执行写入(实现写入的类似串行的行为):
func addBlockToArray(block: @escaping () -> Void) {
queue.async(flags: .barrier) {
self.blocksArray.append(block)
}
}
Run Code Online (Sandbox Code Playgroud)
但您现在可以读取数据,如上所述:
let foo = queue.sync {
blocksArray[index]
}
Run Code Online (Sandbox Code Playgroud)
这种模式的好处是写入是同步的,但读取可以相互发生.在这种情况下,这可能并不重要(因此简单的串行队列可能就足够了),但为了完整起见,我包含了这个读写器模式.
如果您正在寻找Swift 2示例,请参阅此答案的先前版本.
对于线程之间的同步,请使用dispatch_sync(不是 _async)和您自己的调度队列(不是全局队列):
class MyArrayBlockClass {
private var queue = dispatch_queue_create("andrew.myblockarrayclass", nil)
func addBlockToArray(block: () -> Void) {
dispatch_sync(queue) {
self.blocksArray.append(block)
}
}
//....
}
Run Code Online (Sandbox Code Playgroud)
dispatch_sync很好而且易于使用,应该足以满足您的情况(我目前使用它来满足所有线程同步需求),但您也可以使用较低级别的锁和互斥锁。Mike Ash 有一篇很棒的文章,介绍了不同的选择:锁、线程安全和 Swift
| 归档时间: |
|
| 查看次数: |
10082 次 |
| 最近记录: |