2014-11-14 37 views
0

我有一個recursive_mutex我試圖解決的情況。這是解釋問題的一段代碼。如何避免recursive_mutex

void OnConnectionDisconnected() 
    { 
     boost::lock_guard<boost::mutex> lock (m_mutexConnectionSet);  
     IPCSyncConnectionSharedPtrSet::iterator it =  m_IPCSyncConnectionSet.find(spConnection); 
     if (it != m_IPCSyncConnectionSet.end()) 
     { 
      m_IPCSyncConnectionSet.erase(*it);  
     } 
    } 

    void ShutdownServer() 
    { 
     boost::lock_guard<boost::mutex> lock (m_mutexConnectionSet);  
     IPCSyncConnectionSharedPtrSet::iterator it = m_IPCSyncConnectionSet.begin();  
     for (; it != m_IPCSyncConnectionSet.end();) 
     { 
      if (*it) 
      { 
       IPCSyncConnectionSharedPtr spIPCConnection = (*it); 
       it++; 

       //This call indirectly calls OnConnectionDisconnected and erase the connection. 
       spIPCConnection->Disconnect(); 
      } 
      else 
      { 
       ++it; 
      } 
     } 
    } 

OnConnectionDisconnected上調用多個線程(n)的,以及ShutdownServer在當連接處於活動狀態或斷開連接的任何時間被調用上只有一個線程。 ShutdownServer迭代所有連接並調用每個間接調用OnConnectionDisconnected的Disconnect,其中我實際上刪除了連接。我在訪問m_IPCSyncConnectionSet之前鎖定了互斥體,因爲連接集在其他線程中被修改。

我需要在上面的示例代碼中使用recursive_mutex,因爲在調用Shutdown時,互斥鎖在同一個線程上被鎖定兩次。

任何人都可以建議如何解決上述問題,並避免recursive_lock? recurive_mutex會殺了你按這篇文章http://www.fieryrobot.com/blog/2008/10/14/recursive-locks-will-kill-you/

感謝,

回答

2

ShutdownServer()工作與容器的臨時副本。除了鎖定問題之外,迭代由另一個函數修改的容器並不是一個好主意(即使這種特定的容器類型在擦除元素時不會使所有迭代器無效,這樣的代碼將非常脆弱並且不必要的複雜)。

void ShutdownServer() 
{ 
    boost::lock_guard<boost::mutex> lock (m_mutexConnectionSet); 
    auto connections = m_IPCSyncConnectionSet; 
    lock.unlock(); 
    for (auto it = connections.begin(); it != connections.end(); ++it) 
     if (*it) 
     (*it)->Disconnect(); 
} 

現在你既不需要關心鎖定,也不關心迭代器的有效性。

+0

謝謝,這很有幫助,但很簡單。 – user832096