How is it possible to lock a GMutex twice?
I have a test program that I wrote to try and debug a GMutex issue that I am having and I cannot seem to figure it out. I am using the class below to lock and unlock a mutex within a scoped context. This is similar to BOOST's guard.
/// @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* 开发者_如何学CapMutex;
/// 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);
}
};
Using this class, I call it as follows:
bool van::cSessionManager::RegisterSession(const std::string &iSessionId)
{
cSessionMutex lRegistryLock (apRegistryLock);
// SOME CODE
}
where apRegistryLock is a member variable of type GMutex* and is initialized using g_mutex_new() before I ever call RegisterSession.
With this said, when I run the application with several threads, I sometimes notice at the beginning, when RegisterSession is called for the first few times that the log (from the constructor above)
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14ad7ae10
[DEBUG] LOG.-> - MUTEX LOCK 0x26abb40,0x7fc14af7ce10
is logged twice in a row with the same mutex but different instance; therefore, suggesting that the mutex is being locked twice or the second lock is simply being ignored - which is seriously bad.
Moreover, it is worth noting that I also check to see if these logs were initiated from the same thread using the g_thread_self() function, and this returned two separate thread identifiers; thus, suggesting that the mutex was locked twice from separate threads.
So my question is, how is it possible for this to occur?
If it's called twice in the same call chain in the same thread this could happen. The second lock is typically (although not always) ignored. At least in pthreads it's possible to configure multiple locks as counted.
What was happening in my case was there was another thread that was calling g_cond_timed_wait function with the same mutex, but with the mutex unlocked. In this case, g_cond_timed_wait function unlocks a mutex that is not locked and leaves the mutex in an undefined state, which explains why I was seeing the behaviour explained in this question: the mutex being locked twice.
精彩评论