增加生产者消费者的并发性

时间:2015-11-24 12:43:25

标签: c++ multithreading mutex semaphore producer-consumer

我正在解决一种特定的生产者 - 消费者,如下所示 - 有一个大小为<authentication mode="Windows"/> 的缓冲区。消费者从缓冲区中获取项目,一次一个项目(我的意思是,只要消费者线程有权访问缓冲区,它就不会占用多个项目)。只要缓冲区为空,就必须调用生产者。生产者完全填充此缓冲区,然后阻止自己直到再次进行调用。我已经将每个生产者和消费者建模为一个线程并以这种方式实现 -

n

问题是,我使用单个锁来获得完整的缓冲区。因此,在任何时候,只有一个消费者可以拿一件物品。但是当缓冲区尺寸较大时,允许更多消费者同时携带物品是有意义的。我该如何实现?

3 个答案:

答案 0 :(得分:0)

你不能;如果你这样做那么你怎么知道多个消费者不采用相同的元素?对于单个生成器缓冲区,您确实需要一个锁,以便一次安全地删除一个项(按顺序)。因此,您无法并行化从该队列/缓冲区中获取项目,但可以并行化值的处理

// consumer
while (true) {
    item = fetchItemFromBuffer();
    process( item );
}

fetchItemFromBuffer() {
    lock(bufferLock);
    while (buffer.isEmpty()) {
        signal(producerSemaphore);
        wait(consumerSemaphore,bufferLock);
    }
    item = buffer.remove( 0 ); 
    unlock(bufferLock);
    return item;
}

答案 1 :(得分:0)

我认为您可以安全地从缓冲区中删除项目,将其标记为false。只需使这个操作成为原子。例如:

// consumer
getTheItem(buffer);
if( item != false)
    checkAndChange(item);

checkAndChange(item):
    if( item != false)
        atomicChange(item)

你可以只为生产者锁定缓冲区。另一种方法是使用无锁结构。

答案 2 :(得分:0)

一个相对简单的想法是将缓冲区分成块。

例如,假设您有一个1024大小的缓冲区。您可以将其分成64个大小为16的块,或者以适合您需要的任何其他方式。

然后,您需要为每个块使用互斥锁。然后,每个消费者决定要删除哪个元素,然后继续锁定相应的块。但是,如果最初选择的块只有false值,则可能需要重新选择并锁定其他块。

另一种方法是无锁编程,但这取决于你想要进入多远。这里有一个很好的介绍:http://preshing.com/20120612/an-introduction-to-lock-free-programming/