【问题标题】:NSCondition, what if no lock when call signal?NSCondition,调用信号时如果没有锁怎么办?
【发布时间】:2015-01-16 01:51:12
【问题描述】:

this Apple's document about NSConditionNSCondition的用法应该是:

头 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:

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

我的问题是:

我不希望 Thread 2 在任何情况下都被阻塞,因此我删除了 Thread 2 中的 lockunlock 调用。也就是说,线程 2 可以放任意多的工作,线程 1 会一个一个地完成工作,如果没有更多工作,它会等待(阻塞)。这也是生产者-消费者模式,但生产者从未被阻塞。

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

【问题讨论】:

    标签: ios objective-c multithreading nscondition


    【解决方案1】:

    当多个线程访问共享数据时,锁定失败是一个严重的问题。在 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())在没有锁的情况下完成。但是,如果共享数据比这更复杂(并且可能在任何不平凡的情况下),那么他们确实需要使用条件锁等同步机制。

    【讨论】:

    • 谢谢肯。我正在处理的实际情况是生产者-消费者模式,我使用 NSMutableArray 来实现它。一个线程向其中添加对象,另一个线程取出对象。当没有对象时,消费者线程等待。但我不希望生产者线程被阻塞。有什么方法可以实现吗?
    • 必须同步对NSMutableArray的访问。在其他线程可能正在访问它时对其进行变异是不安全的。您可以用来同步访问的一种机制是将所有访问作为任务放在串行 GCD 队列上。推送可以是异步的。这将允许生产者继续使用 GCD 队列作为辅助的、线程安全的数据结构。但是,您的生产者无限期地领先于您的消费者有什么意义呢?您最终需要它停止并等待消费者赶上来,否则您将消耗内存和其他资源。
    • 是的,我明白了,非常感谢。就我的情况而言,它是一个消息发送者,用户可以在屏幕上连续点击或移动以产生许多消息,而另一个线程 - 消费者 - 将消息发送出去。所以主线程(生产者)不能被阻塞。
    • 您可以将生产者分派到异步串行队列中。这可以在不影响您的 UI 的情况下阻止
    猜你喜欢
    • 1970-01-01
    • 2015-07-08
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多