是的,可以在同一个线程中多次等待互斥锁。文档说了这么多:
  在线程获得互斥锁的所有权后,它可以在重复调用等待函数时指定相同的互斥锁,而不会阻塞其执行。这可以防止线程在等待它已经拥有的互斥锁时自行死锁。为了在这种情况下释放它的所有权,每次互斥锁满足等待函数的条件时,线程必须调用一次 ReleaseMutex。
话虽如此,您的代码并不安全,因为您忽略了等待的结果,因此在访问受互斥锁保护的内容之前,您无法确保自己确实拥有互斥锁。
试试这个:
class CMutex
{
public:
    CMutex(const TCHAR *name = NULL);
    ~CMutex();
    bool Enter(DWORD milli = INFINITE);
    void Leave();
};
CMutex::CMutex(const TCHAR *name)
   :  m_hMutex(CreateMutex(NULL, FALSE, name))   
{
}
CMutex::~CMutex()
{
    if (m_hMutex != NULL)
    {
        CloseHandle(m_hMutex);
        m_hMutex = NULL;
    }
}
bool CMutex::Enter(DWORD milli)
{
    return (WaitForSingleObject(m_hMutex, milli) == WAIT_OBJECT_0);
}
void CMutex::Leave()
{
    ReleaseMutex(m_hMutex);
}
void A()
{
    if (mutexObj->Enter()) // <-- CHECK THE RESULT!!!
    {
        B();
        mutexObj->Leave();
    }
}
void B()
{
    if (mutexObj->Enter()) // <-- CHECK THE RESULT!!!
    {
        C();
        mutexObj->Leave();
    }
}
我会更进一步,使用 RAII 来管理锁:
class CMutex
{
public:
    CMutex(const TCHAR *name = NULL);
    ~CMutex();
    bool Enter(DWORD milli = INFINITE);
    void Leave();
    class Lock
    {
    private:
        CMutex &m_mutex;
        bool m_locked;
    public:
        Lock(CMutex &mutex);
        ~Lock();
        bool isLocked() const;
    };
};
CMutex::CMutex(const TCHAR *name)
   :  m_hMutex(CreateMutex(NULL, FALSE, name))   
{
}
CMutex::~CMutex()
{
    if (m_hMutex != NULL)
    {
        CloseHandle(m_hMutex);
        m_hMutex = NULL;
    }
}
bool Enter(DWORD milli)
{
    return (WaitForSingleObject(m_hMutex, milli) == WAIT_OBJECT_0);
}
void Leave()
{
    ReleaseMutex(m_hMutex);
}
CMutex::Lock::Lock(CMutex &mutex)
    : m_mutex(mutex), m_locked(mutex.Enter())
{
}
CMutex::Lock::~Lock()
{
    if (m_locked)
    {
        m_mutex.Leave();
        m_locked = false;
    }
}
CMutex::Lock::isLocked() const
{
    return m_locked;
}
void A()
{
    CMutex::Lock lock(*mutexObj);
    if (lock.isLocked()) // <-- CHECK THE RESULT!!!
        B();
}
void B()
{
    CMutex::Lock lock(*mutexObj);
    if (lock.isLocked()) // <-- CHECK THE RESULT!!!
        C();
}
甚至:
class CMutex
{
public:
    CMutex(const TCHAR *name = NULL);
    ~CMutex();
    bool Enter(DWORD milli = INFINITE);
    void Leave();
    class Lock
    {
    private:
        CMutex &m_mutex;
    public:
        Lock(CMutex &mutex);
        ~Lock();
    };
};
CMutex::CMutex(const TCHAR *name)
   :  m_hMutex(CreateMutex(NULL, FALSE, name))   
{
    if (!m_hMutex)
        throw std::runtime_error("cannot create the mutex handle");
}
CMutex::~CMutex()
{
    CloseHandle(m_hMutex);
    m_hMutex = NULL;
}
bool Enter(DWORD milli)
{
    return (WaitForSingleObject(m_hMutex, milli) == WAIT_OBJECT_0);
}
void Leave()
{
    ReleaseMutex(m_hMutex);
}
CMutex::Lock::Lock(CMutex &mutex)
    : m_mutex(mutex)
{
    if (!m_mutex.Enter())
        throw std::runtime_error("cannot lock the mutex");
}
CMutex::Lock::~Lock()
{
    m_mutex.Leave();
}
void A()
{
    CMutex::Lock lock(*mutexObj);
    B();
}
void B()
{
    CMutex::Lock lock(*mutexObj);
    C();
}