没有正确使用NSLock,但似乎仍然有效

时间:2013-10-18 13:57:11

标签: objective-c cocoa thread-safety nslock

我遇到线程安全问题。我有一个队列,当我修改内容时导致跨线程的错误。我以前没用过锁,但我想我试试。我为所有操作我的队列的后备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

1 个答案:

答案 0 :(得分:6)

是的,您确实需要使用相同的NSLock实例来锁定对阵列的两次访问。与许多多线程错误一样,由于添加附加代码导致的时序差异,问题可能似乎已消失。或者,它可能只是你(非)幸运,并且当你第二次测试时没有出现问题。

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

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

您还可以使用串行调度队列来序列化对资源的访问。这有几个优点,其中最重要的是能够在不等待当前线程完成工作的情况下将工作分派给它。将工作分配到队列的成本也比取出锁定要便宜。请参阅Apple的并发编程指南的Creating Serial Dispatch Queues部分。