访问错误,多线程,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
我正在尝试将一些示例代码从 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