在多线程中,经常会出现这样一种模式,A线程向队列L中push元素,B线程从队列L中pop元素,为了线程安全,必须在A push的时候加锁,然后在B pop的时候也加锁,这是一个典型的生产者消费者模式,这样显然会降低程序的效率。那么怎样来优化这种情景呢?
我们可以使用翻转队列(又称交换队列)来提高这个模型的效率,设计思想是使用2个队列L1,L2,A还是继续向L1中push元素,但是B从L2中pop元素,然后当L2为空的时候,交换L1和L2,这样,A push的时候还是需要加锁,但是B pop的时候就不用加锁,只需要在交换L1和L2的时候加锁,真正产生冲突只有在交换的时候。这样就极大的减少锁互斥的几率,优化了模型的效率。
代码如下(加锁的代码为伪代码),使用模板实现:
template<typename _OBJ> class SwappingList { public: size_t Add(_OBJ & obj ) { ResGuard<Mutex> lock(m_frontMutex); m_frontList->push_back(obj); return m_frontList->size(); } bool Get(_OBJ & obj ) { if ( m_backList->empty() ) { Swap(); } if ( m_backList->empty() ) { return false; } obj = m_backList->front(); m_backList->pop_front(); return true; } void Swap() { ResGuard<Mutex> lock(m_frontMutex); PRODUCT_LIST * p = m_backList; m_backList = m_frontList; m_frontList = p; } SwappingList() { m_frontList = new PRODUCT_LIST; m_backList = new PRODUCT_LIST; } virtual ~SwappingList() { if ( m_frontList ) { delete m_frontList; m_frontList = 0; } if ( m_backList ) { delete m_backList; m_backList = 0; } } protected: typedef std::list<_OBJ> PRODUCT_LIST; PRODUCT_LIST* m_frontList; PRODUCT_LIST* m_backList; Mutex m_frontMutex; };