如何避免recursive_mutex

How to avoid recursive_mutex

本文关键字:mutex recursive 何避免      更新时间:2023-10-16

我有一个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;
            }
        }
    }

OnConnection断开连接在多个线程上调用(n),并且在连接处于活动状态或断开连接时,任何时候仅在一个线程上调用ShutdownServer。关闭服务器遍历所有连接并在每个连接上调用断开连接,这间接调用OnConnection断开连接,我实际上擦除了连接。我在访问m_IPCSyncConnectionSet之前锁定了互斥锁,因为连接集在其他线程中被修改。

我需要在上面的示例代码中使用recursive_mutex,因为当调用 Shutdown 时,互斥锁在同一线程上被锁定两次。

任何人都可以建议如何解决上述问题并避免recursive_lock? recurive_mutex会按照这篇文章杀死你 http://www.fieryrobot.com/blog/2008/10/14/recursive-locks-will-kill-you/

谢谢

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();
}

现在,您既不需要关心锁定,也不需要关心迭代器的有效性。