访问错误,多线程,ICD,swift

Bad acess, multi-threading, GCD, swift

我正在尝试将一些示例代码从 objective-c 翻译成 swift!

除了对本次模拟至关重要的多线程部分外,我已经全部正常工作了。

出于某种原因,当我开始使用多线程时出现访问错误。特别是在从数组中获取或设置内容时。

此 class 在静态 class 中实例化。

var screenWidthi:Int = 0
var screenHeighti:Int = 0
var poolWidthi:Int = 0
var poolHeighti:Int = 0

var rippleSource:[GLfloat] = []
var rippleDest:[GLfloat] = []

func update()
{
        let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

        dispatch_apply(Int(poolHeighti), queue, {(y: size_t) -> Void in
        //for y in 0..<poolHeighti
        //{
            let pw = self.poolWidthi
            for x in 1..<(pw - 1)
            {
                let ai:Int = (y    ) * (pw + 2) + x + 1
                let bi:Int = (y + 2) * (pw + 2) + x + 1
                let ci:Int = (y + 1) * (pw + 2) + x
                let di:Int = (y + 1) * (pw + 2) + x + 2
                let me:Int = (y + 1) * (pw + 2) + x + 1

                let a = self.rippleSource[ai]
                let b = self.rippleSource[bi]
                let c = self.rippleSource[ci]
                let d = self.rippleSource[di]

                var result = (a + b + c + d) / 2.0 - self.rippleDest[me]
                result -= result / 32.0

                self.rippleDest[me] = result
            }
        }
        )
}

重要的是要注意,在这个循环之后还有另一个循环应该 运行 在不同的线程上,它访问相同的数组。话虽这么说,如果没有第二个在另一个线程中,它仍然会很糟糕,所以我觉得它是无关紧要的。

如果你能告诉我是什么原因导致这次崩溃随机发生,而不是第一次发生。

如果你想参考这里是objective c

中的样子
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(poolHeight, queue, ^(size_t y) {
        for (int x=0; x<poolWidth; x++)
        {
            float a = rippleSource[(y)*(poolWidth+2) + x+1];
            float b = rippleSource[(y+2)*(poolWidth+2) + x+1];
            float c = rippleSource[(y+1)*(poolWidth+2) + x];
            float d = rippleSource[(y+1)*(poolWidth+2) + x+2];

            float result = (a + b + c + d)/2.f - rippleDest[(y+1)*(poolWidth+2) + x+1];

            result -= result/32.f;

            rippleDest[(y+1)*(poolWidth+2) + x+1] = result;
        }            
    });

如何确保变量可以从不同的线程访问?静态成员怎么样?

我只是不知道如何在应用程序崩溃之前打印出调用堆栈,但是之后,我知道进入调用堆栈的唯一方法是查看线程。让我知道是否有其他方法可以做到这一点。

注意:我注意到一些奇怪的事情。我在每个循环中放置了一个打印语句,这样我就可以看到它正在处理的 x 和 y 坐标,以确定崩溃是否一致。令人讨厌的是,这使 fps 降至 1 fps 以下,但我确实注意到它尚未崩溃。到目前为止,该程序 运行 非常完美,没有任何不良访问,只有不到 1 fps。

Apple 代码使用的是 C 风格的数组,这些是 "thread safe" 如果使用得当 - 正如 Apple 代码所做的那样。

Swift 和 Objective-C,数组 不是 线程安全的,这是导致问题的原因。您需要对数组实施某种形式的访问控制。

一个简单的方法就是给每个数组关联一个GCD顺序队列,然后写入数组dispatch async到这个队列,读dispatch sync。这很简单但降低了并发性,使其更好地阅读Mike Ash。对于 Swift 代码

如果您需要了解问题,Mike Ash 是个好人,对于 Swift 编写代码并查看 this question - 阅读所有答案 评论。

HTH