我正在解决一种特定的生产者 - 消费者,如下所示 -
有一个大小为<authentication mode="Windows"/>
的缓冲区。消费者从缓冲区中获取项目,一次一个项目(我的意思是,只要消费者线程有权访问缓冲区,它就不会占用多个项目)。只要缓冲区为空,就必须调用生产者。生产者完全填充此缓冲区,然后阻止自己直到再次进行调用。我已经将每个生产者和消费者建模为一个线程并以这种方式实现 -
n
问题是,我使用单个锁来获得完整的缓冲区。因此,在任何时候,只有一个消费者可以拿一件物品。但是当缓冲区尺寸较大时,允许更多消费者同时携带物品是有意义的。我该如何实现?
答案 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/