我可以建议两件事,我敢打赌其中之一(或两者)是解决您问题的总体解决方案。
首先,我将k 声明为块的本地,因此毫无疑问您是否正在覆盖它。您可能对块内的kNSNumber 有同样的问题。如果您只是使用该 NSNumber 实例猛击multipliedArrayInto 累加器,您也可以删除kNSNumber,并在它的位置使用@(k)(如果只是为了更具可读性)。同样,确保multipliedArrayInto 在dispatch_apply 之前声明,看起来像一个外部for 循环(i 来自哪里)。最后,确保 resulArray 被实例化,或者在外部 for 循环之前准备好。
其次,queue 是并发队列还是串行队列?如果您使用 dispatch_apply 像并行执行 for/enumeration 一样 - 我认为这很可能,所以您正在有效地处理“大数组” - 那么您实际上可以保证 k 被覆盖。如果您将其更改为串行,它可能会按设计工作。如果您希望它是并行的,则需要将 k 累加器的声明移动到块内,并确保其他变量的声明也有意义。
更新以反映问题更新:
@antonytonies 理想情况下,您对该主题的后续回答应移至问题本身,以便人们可以更轻松地关注该主题。
所以,看来我所描述的正是你的问题。
全局队列都是并发队列,这意味着(假设)所有调度块都在一次执行,k 和其他变量的内容会根据如何被吹走块的执行顺序。
我已获取您的更新(在您添加的“答案”中),并将其修改为可能有效:
// I renamed your method, because nameless parameters pain me. This is cosmetic, and doesn't
// matter for the problem at hand.
- (NSMutableArray *)multiplicationArrays:(NSMutableArray *)array vector:(NSMutableArray *)vector
{
// IMHO, you want to set resultArray to nil here. Another option is to set it to nil in the
// else case, below. Properties in Objective-C are initalized to nil,0,false,etc; you can
// rely on ARC to initialize pointer to objc objects on the stack, too. However, someone
// reading this code may or may not know that. IMHO, using the explicitly assignement makes it
// clear that you're going to be returning `nil` or an instance of `NSMutableArray`.
NSMutableArray *resultArray = nil;
if ([[array objectAtIndex:0] count] == [vector count]) {
// Nicely done w/ pre-allocating the result array here, so that there's no question
// of the indexes matches the results later on.
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
// 'queue' here is a concurrent queue. This means that you are proclaiming to the runtime
// that the blocks being executed are able to operate correctly w/o interference from each
// other. This is also thought of in terms of parallel execution: all these blocks may run
// **at once**. This *also* means, that you must not share storage between them.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j) {
// Moved 'result' inside the block.
NSInteger result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
// These array reads are **NOT** thread safe. They probably don't cause must trouble in
// practice, but you may want to reconfigure this.
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l] intValue];
}
// The replace of the object into resultArray is **NOT** thread-safe.
// This probably hasn't caused you much trouble, since you can guarantee that
// you aren't writing at the same index. However, I would strongly suggest to
// change this to be thread-safe.
[resultArray replaceObjectAtIndex:j withObject:@(result)];
});
}
else {
NSLog(@"matrix count isn't correspond");
}
return resultArray;
}
最后:考虑使用 Apple 的 Accelerate 框架来解决此类问题。它在 OSX 和 iOS 上可用,因此您应该涵盖所有基础。