怎么可能锁定一个GMutex两次?

How is it possible to lock a GMutex twice?

本文关键字:一个 GMutex 两次 锁定 怎么可能      更新时间:2023-10-16

我有一个测试程序,我写了一个测试程序来尝试和调试我所拥有的GMutex问题,我似乎无法弄清楚。我使用下面的类来锁定和解锁一个作用域上下文中的互斥锁。这类似于BOOST的保护。

   /// @brief Helper class used to create a mutex.
   ///
   /// This helper Mutex class will lock a mutex upon creation and unlock when deleted.
   /// This class may also be referred to as a guard.
   ///
   /// Therefore this class allows scoped access to the Mutex's locking and unlocking operations
   /// and is good practice since it ensures that a Mutex is unlocked, even if an exception is thrown.
   ///
   class cSessionMutex
   {
      GMutex* apMutex;
      /// The object used for logging.
      mutable cLog aLog;
   public:
      cSessionMutex (GMutex *ipMutex) : apMutex(ipMutex), aLog ("LOG", "->")
      {
         g_mutex_lock(apMutex);
         aLog << cLog::msDebug << "MUTEX LOCK " << apMutex << "," << this << cLog::msEndL;
      }
      ~cSessionMutex ()
      {
         aLog << cLog::msDebug << "MUTEX UNLOCK " << apMutex << "," << this << cLog::msEndL;
         g_mutex_unlock(apMutex);
      }
   };

使用这个类,我这样调用它:

bool van::cSessionManager::RegisterSession(const std::string &iSessionId)
{
cSessionMutex lRegistryLock (apRegistryLock);
// SOME CODE
}

其中apRegistryLock是GMutex*类型的成员变量,并且在我调用RegisterSession之前使用g_mutex_new()进行初始化。

话虽如此,当我运行带有多个线程的应用程序时,我有时会注意到,在开始的时候,当最初几次调用RegisterSession时,日志(来自上面的构造函数)

[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14ad7ae10
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14af7ce10

在同一个互斥锁不同实例的一行中被记录两次;因此,建议互斥锁被锁定两次,或者第二个锁被忽略——这是非常糟糕的。

此外,值得注意的是,我还检查了这些日志是否是使用g_thread_self()函数从同一个线程发起的,这返回了两个单独的线程标识符;这表明互斥锁在不同的线程中被锁定了两次。

所以我的问题是,这怎么可能发生呢?

如果它在同一线程的同一调用链中被调用两次,则可能发生这种情况。第二个锁通常(尽管并非总是)被忽略。至少在pthreads中可以配置多个锁。

在我的情况下发生的事情是,有另一个线程使用相同的互斥锁调用g_cond_timed_wait函数,但互斥锁已解锁。在本例中,g_cond_timed_wait函数将未锁定的互斥锁解锁,并使互斥锁处于未定义状态,这解释了为什么我看到这个问题中解释的行为:互斥锁了两次。