arrays - Swift 并行性 : Array vs UnsafeMutablePointer in GCD

标签 arrays swift pointers parallel-processing

我发现了一些奇怪的东西:无论出于何种原因,在以下代码运行后,数组版本几乎总是包含随机 0,而指针版本则不会。

var a = UnsafeMutablePointer<Int>.allocate(capacity: N)
//var a = [Int](repeating: 0, count: N)

let n = N / iterations

DispatchQueue.concurrentPerform(iterations: iterations) { j in
    for i in max(j * n, 1)..<((j + 1) * n) {
        a[i] = 1
    }
}

for i in max(1, N - (N % n))..<N {
    a[i] = 1
}

这有什么特殊原因吗?我知道 Swift 数组在内存中可能不是连续的,但是从单个线程访问每个索引的内存位置一次,不应该做任何太有趣的事情。

最佳答案

数组不是线程安全的,尽管它们桥接到 Objective-C 对象,但它们的行为就像具有 COW(写入时复制)逻辑的值类型。当任何元素发生变化且引用计数器大于 1 时,数组上的 COW 将复制整个数组(从概念上讲,实际实现要更微妙一些)。

只要主线程碰巧引用和元素,对数组进行更改的线程就会触发内存复制。主线程也会进行更改,因此也会导致 COW。最终得到的是任一线程使用的最后修改副本的状态。这将随机地留下一些不确定的变化并解释“错过”的项目。

为了避免这种情况,您需要在特定线程中执行所有更改并使用sync()来确保数组上的COW仅由该线程执行(这实际上可能会减少内存副本的数量并为非常大的数组)。不过,使用这种方法会产生开销和潜在的争用。这是为了线程安全而付出的代价。

解决此问题的另一种方法是使用对象数组(引用类型)。这使您的数组成为一个简单的指针列表,这些指针实际上不会通过修改引用对象中的数据而更改。尽管在实际程序中,您需要注意每个对象实例内的线程安全性,但与值类型数组相比,干扰(和开销)要少得多。

关于arrays - Swift 并行性 : Array vs UnsafeMutablePointer in GCD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46011056/

相关文章:

javascript - AngularJS - ForEach 不循环

arrays - 带有动态数组的 DELPHI 类在 SetLength() 中有问题

swift - 如何在 Swift 中创建一个我可以选择调用的完成处理程序?

ios - 如何对 subview 进行动画处理,使其仅在框架范围内进行动画处理?

ios - 从 iOS 推送通知打开项目

c++ - 如何在 64 位系统中将 FILE* 转换为数字句柄?

javascript - 用值拆分数组 - 像 String.split

c++ - 如何创建一个新的字符串数组

pointers - Pointer Arithmetic on pointers to pointers 等

string - 在函数调用中发送 QString 的最佳方法是什么?