在多線程中,經常會出現這樣一種模式,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;
};