在多线程中,经常会出现这样一种模式,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;
}