NSCondition,如果没有锁定呼叫信号怎么办?

时间:2015-01-16 01:51:12

标签: ios objective-c multithreading nscondition

this Apple's document about NSCondition开始,NSCondition的使用应为:

Thead 1:

[cocoaCondition lock];
while (timeToDoWork <= 0)
    [cocoaCondition wait];
timeToDoWork--;
// Do real work here.
[cocoaCondition unlock];

主题2:

[cocoaCondition lock];
timeToDoWork++;
[cocoaCondition signal];
[cocoaCondition unlock];

the document of method signal in NSConditon

  

使用此方法唤醒正在等待条件的一个线程。您可以多次调用此方法来唤醒多个线程。如果没有线程在等待该条件,则此方法不执行任何操作。 为了避免竞争条件,您应该仅在接收器被锁定时调用此方法

我的问题是:

我不希望线程2 在任何情况下都被屏蔽,因此我删除了线程2中的lockunlock电话。也就是说,线程2 可以放置任意数量的工作,线程1 将逐个完成工作,如果没有更多工作,则等待(阻塞)。这也是生产者 - 消费者模式,但生产者从未被封锁。

但根据Apple的文件,方式不正确那么在这种模式中可能会出现什么问题?感谢。

1 个答案:

答案 0 :(得分:2)

当多个线程访问共享数据时,无法锁定是一个严重的问题。在Apple代码的示例中,如果线程2没有锁定条件对象,那么它可以在线程1递减它的同时递增timeToDoWork。这可能导致其中一个操作的结果丢失。例如:

线程1读取timeToDoWork的当前值,得到1
线程2读取timeToDoWork的当前值,得到1
线程2计算递增的值(timeToDoWork + 1),得到2
线程1计算递减的值(timeToDoWork - 1),得到0
线程2写入timeToDoWork的新值,存储2
线程1写入timeToDoWork的新值,存储0

timeToDoWork从1开始,递增和递减,因此它应该以1结束,但它实际上以0结束。通过重新排列步骤,它可能最终为2,而不是。据推测,timeToDoWork的价值代表了真实而重要的东西。错误的做法可能会破坏程序。

如果你的两个线程正在做一些像递增和递减数字那样简单的事情,那么他们可以通过使用原子操作函数(例如OSAtomicIncrement32Barrier()OSAtomicDecrement32Barrier())来做到这一点。但是,如果共享数据比那更复杂(并且它可能在任何非平凡的情况下),那么它们确实需要使用条件锁等同步机制。