我们一直希望在代码中使用一个无锁队列来减少当前实现中单个生产者和使用者之间的锁争用。有很多队列实现,但我还不太清楚如何最好地管理节点的内存管理。
例如,生产者的样子如下:
queue.Add( new WorkUnit(...) );
消费者看起来:
WorkUnit* unit = queue.RemoveFront();
unit->Execute();
delete unit;
我们目前使用内存池进行分配。您会注意到,生产者分配内存,使用者删除它。由于我们使用的是池,因此需要向内存池添加另一个锁,以正确地保护它。这似乎一开始就否定了无锁队列的性能优势。
到目前为止,我认为我们的选择是:
我们还有其他的选择可以探索吗?我们试图避免实现一个无锁的内存池,但我们可能会选择这条路。
谢谢。
发布于 2011-06-23 22:30:51
只有生产者才能创建对象并在不再需要时销毁它们,。使用者只能使用对象并将其标记为已使用的对象。这就是问题所在。在这种情况下,您不需要共享内存。这是我所知道的高效无锁队列实现的唯一方法。
阅读这的伟大文章,其中详细描述了这种算法。
发布于 2011-06-23 22:57:18
另一种可能是为每个线程拥有一个单独的内存池,因此只有一个线程使用堆,您可以避免锁定分配。
这样您就可以管理一个释放块的无锁函数了。幸运的是,这很容易管理:您为每个堆维护了一个空闲块的链接列表。您将块自己的地址放入链接列表的链接字段(您将用作内存),然后与指针进行原子交换,指针保存链接列表的头。
发布于 2011-06-23 22:31:51
你应该看看英特尔的TBB。我不知道商业项目要花多少钱,但是他们已经有了并发队列,并发内存分配器,诸如此类的东西。
队列接口看起来也很不可靠--例如,您的RemoveFront()调用--如果队列是空的怎么办?new
和delete
调用看起来也相当冗余。英特尔的TBB和微软的PPL (包括在VS2010中)没有受到这些问题的影响。
https://stackoverflow.com/questions/6461236
复制相似问题