添加项目在多个线程斯威夫特阵列引起的问题(因为数组不是线程安全的) - 我该如何解决呢? [英] Adding items to Swift array across multiple threads causing issues (because arrays aren't thread safe) - how do I get around that?

查看:144
本文介绍了添加项目在多个线程斯威夫特阵列引起的问题(因为数组不是线程安全的) - 我该如何解决呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想给块添加到一个数组,然后要求运行时包含在数组中,所有块。我也与此类似code:

 类MyArrayBlockClass {
    私人VAR blocksArray:数组≤() - GT;虚空> =阵列()    私人让利blocksQueue:NSOperationQueue()    FUNC addBlockToArray(块:() - GT;无效){
        self.blocksArray.append(块)
    }    FUNC runBlocksInArray(){
        在self.blocksArray {块
            让操作= NSBlockOperation(块:块)
            self.blocksQueue.addOperation(操作)
        }        self.blocksQueue.removeAll(keepCapacity:FALSE)
    }
}

问题出现的事实,addBlockToArray可以在多个线程调用。这是怎么回事是addBlockToArray被称为跨不同的线程接二连三,仅追加的项目之一,因此其他项目,因此不得到runBlocksInArray过程中调用。

我已经试过这样的事情,这似乎并不奏效:

 私人让blocksDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)FUNC addBlockToArray(块:() -  GT;无效){
    dispatch_async(blocksDispatchQueue){
        self.blocksArray.append(块)
    }
}


解决方案

您告诉我们,企图:

 私人让blocksDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)FUNC addBlockToArray(块:() -  GT;无效){
    dispatch_async(blocksDispatchQueue){
        self.blocksArray.append(块)
    }
}

事情是,这是一个并发队列,所以你没有达到你想要的同步。但是,如果你创建了自己的串行队列中,那会是精致的,例如:

 私人让blocksDispatchQueue = dispatch_queue_create(com.domain.blocksArray.sync,无)

另外,还要确保你也同步派遣所有读取到相同的队列:

  dispatch_sync(blocksDispatchQueue){
    someVariable = self.blocksArray [指数]
}

这一切互动 blocksArray 应通过此队列进行协调。


另外,您还可以使用读/写器模式,创建自己的并发队列:

 私人让blocksDispatchQueue = dispatch_queue_create(com.domain.blocksArray.sync,DISPATCH_QUEUE_CONCURRENT)

然后写使用屏障数据:

  FUNC addBlockToArray(块:() -  GT;无效){
    dispatch_barrier_async(blocksDispatchQueue){
        self.blocksArray.append(块)
    }
}

但你现在可以读取数据,像上面:

  dispatch_sync(blocksDispatchQueue){
    someVariable = self.blocksArray [指数]
}

此模式的好处是,写操作被同步,但读取可相对于彼此同时发生。

I want to add given blocks to an array, and then run all the blocks contained in the array, when requested. I have code similar to this:

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)
    }
}

The problem comes with the fact that addBlockToArray can be called across multiple threads. What's happening is addBlockToArray is being called in quick succession across different threads, and is only appending one of the items, and so the other item is therefore not getting called during runBlocksInArray.

I've tried something like this, which doesn't seem to be working:

private let blocksDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

func addBlockToArray(block: () -> Void) {
    dispatch_async(blocksDispatchQueue) {
        self.blocksArray.append(block)
    }
}

解决方案

You show us an attempt:

private let blocksDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

func addBlockToArray(block: () -> Void) {
    dispatch_async(blocksDispatchQueue) {
        self.blocksArray.append(block)
    }
}

Thing is, that's a concurrent queue, so you're not achieving the synchronization you want. But if you created your own serial queue, that would have been fine, e.g.:

private let blocksDispatchQueue = dispatch_queue_create("com.domain.blocksArray.sync", nil)

Also make sure that you also synchronously dispatch all reads to the same queue:

dispatch_sync(blocksDispatchQueue) {
    someVariable = self.blocksArray[index]
}

All interaction with this blocksArray should be coordinated through this queue.


Alternatively, you can also employ the reader/writer pattern, creating your own concurrent queue:

private let blocksDispatchQueue = dispatch_queue_create("com.domain.blocksArray.sync", DISPATCH_QUEUE_CONCURRENT)

Then write data using barrier:

func addBlockToArray(block: () -> Void) {
    dispatch_barrier_async(blocksDispatchQueue) {
        self.blocksArray.append(block)
    }
}

But you can now read data, like above:

dispatch_sync(blocksDispatchQueue) {
    someVariable = self.blocksArray[index]
}

The benefit of this pattern is that writes are synchronized, but reads can occur concurrently with respect to each other.

这篇关于添加项目在多个线程斯威夫特阵列引起的问题(因为数组不是线程安全的) - 我该如何解决呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆