3

我遇到了线程安全问题。我有一个队列,当我修改内容时会导致跨线程出错。我以前没有用过锁,但我想我试试。我在所有为我的队列操作支持 NSMutableArray 的代码周围添加了一个锁。我认为,问题在于我没有为所有人使用相同的锁。我在每个修改数组的方法中创建了一个新的 NSLock 实例。我假设我应该使用一个 NSLock ivar 来保护阵列。但我的困惑来自于我添加它后它就起作用了。下面是一个示例。我假设在任何地方我创建了一个新的 NSLock,我应该只使用一个 ivar NSLock。我认为这段代码只是将入队锁定在其他入队和出队对其他出队而不是入队对出队。澄清会很棒。

@implmentation

...    

- (void)enqueue:(id)obj
{
  NSLock *arrayLock = [[NSLock alloc] init];
  [arrayLock lock];
   [_backingStore addObject:obj];
  [arrayLock unlock];
}

- (id)dequeue
{
  NSLock *arrayLock = [[NSLock alloc] init];
  [arrayLock lock];
  id result = [_backingStore firstObject];

  if( result )
  {
    [_backingStore removeObjectAtIndex:0];
  }

  [arrayLock unlock];
  return result;
}

...

@end
4

1 回答 1

6

是的,您确实需要使用相同的 NSLock 实例来锁定对数组的两次访问。与许多多线程错误一样,由于添加额外代码导致的时间差异,问题似乎已经消失。或者,可能只是你运气不好,第二次测试时问题没有出现。

无论如何,NSLock 只是在 Objective-C 中锁定对关键部分的访问的一种方式。@synchronized()从代码复杂性的角度来看,您还可以使用which 可能更容易:

@synchronized(someSharedToken) {
    // Do your array access here
}

您还可以使用串行调度队列来序列化对资源的访问。这有几个优点,其中最重要的是能够将工作分派给它,而无需等待该工作在当前线程上完成。将工作分派到队列也比取出锁更便宜。请参阅 Apple 并发编程指南的创建串行调度队列部分。

于 2013-10-18T16:12:22.670 回答