我在多线程中遇到了一个问题,多线程模型是1生产者 - N消费者。
生产者生成数据(每个字符数据大约200字节),将其放入固定大小的缓存(即2Mil)。数据与所有线程无关。它应用过滤器(已配置)并确定没有符合生成数据的线程。
生产者将指向数据的指针推送到合格线程的队列中(仅指向数据的指针以避免数据复制)。线程将deque并通过TCP / IP发送给客户端。
问题:由于只有指向数据的指针被赋予多个线程,当缓存变满时,Produces想要删除第一个项目(旧的)。任何线程仍然可以引用数据的可能性。
可行的方法:使用Atomic粒度,当生产者确定合格线程的数量时,它可以更新计数器和线程ID列表。
class InUseCounter
{
int m_count;
set<thread_t> m_in_use_threads;
Mutex m_mutex;
Condition m_cond;
public:
// This constructor used by Producer
InUseCounter(int count, set<thread_t> tlist)
{
m_count = count;
m_in_use_threads = tlist;
}
// This function is called by each threads
// When they are done with the data,
// Informing that I no longer use the reference to the data.
void decrement(thread_t tid)
{
Gaurd<Mutex> lock(m_mutex);
--m_count;
m_in_use_threads.erease(tid);
}
int get_count() const { return m_count; }
};
掌握chache
map<seqnum, Data>
|
v
pair<CharData, InUseCounter>
当生产者移除它检查计数器的元素时,它大于0,它发送动作以释放对m_in_use_threads集中线程的引用。
问题
感谢您的建议。
答案 0 :(得分:4)
InUseCounter
放在一个结构中会导致线程在释放记录时发生争用;如果线程没有以锁步方式执行,这可能是微不足道的。如果他们经常发布记录并且争用率上升,这显然是性能下降。顺便提一下,这与Disruptor框架的工作方式类似。它是用于高频交易的高性能Java(!)并发框架。是的,我确实在同一句话中说过高性能的Java和并发性。对高性能并发设计和实现有很多宝贵的见解。
答案 1 :(得分:1)
由于您已经拥有Producer->Consumer
队列,因此一个非常简单的系统包含一个“反馈”队列(Consumer->Producer
)。
在使用了一个项目后,消费者将指针反馈给Producer,以便Producer可以删除该项目并更新缓存的“空闲列表”。
这样,只有Producer会触及缓存内部,并且不需要同步:只需要同步队列。
答案 2 :(得分:0)