在Apple的并发编程指南的“远离线程迁移”部分中,有 Changing Producer-Consumer Implementations,声称可以使用GCD简化典型的多步pthread互斥+条件变量实现。
使用调度队列,您可以简化生产者和消费者 实现为单个调用:
dispatch_async(queue, ^{
// Process a work item.
});
当您的生产者要完成工作时,它所要做的就是将该工作添加到队列中并让队列处理该项目。
生产者 - 消费者问题也被称为有界缓冲问题,但上面没有提到缓冲区,它的界限或消费者,更不用说阻止生产者和放大器了。消费者,以避免过度/不足。
这怎么可能是一个有效的解决方案?
答案 0 :(得分:22)
在Apple文件中描述的解决方案中:
假设您有多个生产者和消费者,生产者将数据放在共享缓冲区中,而消费者从该共享缓冲区中读取数据。信号量或监视器用于同步对共享缓冲区的访问,并且缓冲区大小是固定的,以便根据它们消耗的速率限制正在生成的数据量,从而限制生产者。
在Grand Central Dispatch下,消费者是派遣到队列的任务。由于任务是Objective-C块,生产者不需要缓冲区来告诉消费者它应该处理的数据:Objective-C块自动捕获它们引用的对象。
例如:
// Producer implementation
while (…) {
id dataProducedByTheProducer;
// Produce data and place it in dataProducedByTheProducer
dataProducedByTheProducer = …;
// Dispatch a new consumer task
dispatch_async(queue, ^{
// This task, which is an Objective-C block, is a consumer.
//
// Do something with dataProducedByTheProducer, which is
// the data that would otherwise be placed in the shared
// buffer of a traditional, semaphore-based producer-consumer
// implementation.
//
// Note that an Objective-C block automatically keeps a
// strong reference to any Objective-C object referenced
// inside of it, and the block releases said object when
// the block itself is released.
NSString *s = [dataProducedByTheProducer …];
});
}
生产者可以放置与其可以生成的数据一样多的消费者任务。但是,这并不意味着GCD将以相同的速率启动消费者任务。 GCD使用操作系统信息来控制根据当前系统负载执行的任务量。生产者本身没有受到限制,在大多数情况下,它不一定是因为GCD的内在负载平衡。
如果实际需要限制生产者,一个解决方案是让主人调度 n 生产者任务并让每个消费者通知主人(通过在消费者完成后调度的任务)它已经结束,在这种情况下,主人将派遣另一个生产者任务。或者,消费者本身可以在完成时派遣生产者任务。
具体回答您已解决的问题:
Producer-Consumer问题也称为Bounded-Buffer问题,但上面没有提到缓冲区
不需要共享缓冲区,因为使用者是Objective-C块,它会自动捕获它们引用的数据。
其约束
GCD根据当前系统负载限制调度任务的数量。
或消费者
消费者是派遣到GCD队列的任务。
更不用说阻止制片人了消费者,以避免过度/不足
由于没有共享缓冲区,因此无需阻塞。由于每个使用者都是一个Objective-C块,通过Objective-C块上下文捕获机制捕获生成的数据,因此消费者和数据之间存在一对一的关系。