【问题标题】:On iOS, how to implement blocking or "being blocked" on a thread that produces data?在 iOS 上,如何在产生数据的线程上实现阻塞或“被阻塞”?
【发布时间】:2012-08-19 14:08:16
【问题描述】:

如果我们需要实现一个队列(由NSMutableArray 完成),并且我们有Producer 将数据添加到队列的对象。可以有 1 个生产者或多个生产者。如果队列已满(例如,大小为 100),则线程应该被“阻塞”(等待,直到队列实际上小于 100 个项目)。 (从队列中取出数据也是如此:当队列为空时,数据的获取也被阻塞)。

如何实现这种“阻塞”?现在我使用互斥锁

@property (strong, atomic) NSLock *lock;

这样就可以得到NSMutableArray的count和item的加法(因为count可以是99,但是加item的时候count可能已经不一样了)。

但是对于阻塞效果,我其实是去查count的,如果是100,就释放锁,休眠0.1秒,然后再次获取锁,获取count,如上重复。

这是实现“阻塞”行为的好方法吗?似乎还有另一种方法可以得到canAddNowLock,就是简单的被NSLock机制阻塞,当一个队列项被移除后,再释放这个canAddNowLock,但是由于可以有多个数据生产者和数据消费者,如果多个生产者被解锁,或者如果多个消费者连续解锁canAddNowLock并且只有一个生产者被解锁(实际上应该解锁多个生产者)怎么办?这样一来,设计看起来就更复杂了。

【问题讨论】:

    标签: ios multithreading blocking blockingqueue


    【解决方案1】:

    使用 NSCondition *condition 线程1:

    [condition lock];
    //check the queue is not full
    [condition wait];//if already full, wait
    //check again
    //put something into queue
    [condition unlock];
    

    线程2:

    [condition lock];
    //check the queue is not empty
    //get something from queue
    [condition signal];
    [condition unlock];
    

    【讨论】:

    • 对于thread1,所以[condition wait]和[check again]需要循环吗? (但由于signal 唤醒了 1 个线程(即使有多个线程在等待,所以也许这已经可以完成这项工作了……甚至不需要在 //check again 进行第二次检查?)
    • 对于多线程,可以使用[条件广播]来唤醒所有线程。第二个检查是为了安全,多线程不能太小心。
    • 所以如果要小心,那么“检查和等待”不需要循环吗? (但即使第二次检查,如果有错误,那么即使在第二次检查和添加数据之间,也可能已经在其他地方发生了一些不良影响......(顺便说一下我检查了 7顶级 iOS 书籍,包括 2 本食谱,但没有一本在索引部分有 NSCondition,但有 2 个官方 Apple iOS 指南涵盖了它)
    • 如果你总是使用这个条件来保护你的队列,你在[条件等待]和[条件解锁]之间持有锁,所以其他线程不能操作队列,它足够安全。您应该进行双重检查的另一个原因是,当您 [条件等待] 时,您实际上释放了锁,因此在您再次获取它之前可能会发生任何事情。是否使用循环取决于你的应用程序的逻辑,我给你的代码sn-p只是为了启发你。
    • 我的意思是,如果第二次检查实际上返回队列已满,那么 [condition wait] 不需要再次执行,然后第三次检查,等等...并且可能进行第四次检查和另一次等待,这是否意味着它需要处于循环中?
    猜你喜欢
    • 1970-01-01
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多