C++:如何简化线程锁定

C++: How To Simplified Thread Lock?

本文关键字:线程 锁定 何简化 C++      更新时间:2023-10-16

我是C++的新手。在学习线程如何工作时,我发现在开始时调用WaitForSingleObject(x),在结束时调用ReleaseMutex(x)非常烦人。所以我写了一节课来为我做这件事,但我不确定影响,我做得对吗。想知道有没有更简单的方法来实现同样的目的?我是这样做的:

class MutexLock {
public:
    MutexLock(HANDLE hMutex) {
        m_hMutex = hMutex;
    }
    void    Lock() {
        WaitForSingleObject((m_hMutex), INFINITE);
    }
~MutexLock() {
    if (m_hMutex != NULL) {
        ReleaseMutex(m_hMutex);
        std::cout << "Mutex released." << std::endl;
    }
}
private:
    HANDLE  m_hMutex;
};

以及我如何使用该类:

class TestMutex
{
public:
    TestMutex(void) {
        m_mutex = CreateMutex(NULL, FALSE, NULL);
        std::cout << "Mutex created." << std::endl;
    }
    ~TestMutex(void) {
        if (m_mutex != NULL)
            CloseHandle(m_mutex);
    }
    void    Func1(void) {
        MutexLock ml(m_mutex);
        ml.Lock();
        std::cout << "Func1: Owning mutex." << std::endl;
        std::cout << "Press enter key to end this." << std::endl;
        ReadKey(GetStdHandle(STD_INPUT_HANDLE));
    }
    void    Func2(void) {
        MutexLock ml(m_mutex);
        ml.Lock();
        //std::cout << "Press enter key to start this." << std::endl;
        //ReadKey(GetStdHandle(STD_INPUT_HANDLE));
        std::cout << "Func2: Owning mutex." << std::endl;
        std::cout << "Press enter key to end this." << std::endl;
        ReadKey(GetStdHandle(STD_INPUT_HANDLE));
    }
private:
    HANDLE  m_mutex;
};

在主要功能:

int _tmain(int argc, _TCHAR* argv[])
{
    TestMutex * tm = new TestMutex();
    HANDLE aThread[2];
    for (int i = 0; i < 2; i++)
    {
        aThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)tm, 0, 0);
    }
    WaitForMultipleObjects(2, aThread, TRUE, INFINITE);
    for (int i = 0; i < 2; i++)
    {
        CloseHandle(aThread[i]);
    }
    delete tm;
    ReadKey(GetStdHandle(STD_INPUT_HANDLE));
    return 0;
}

其他人通常是这样做线程锁定的吗?

实际上,您允许类API的使用者滥用它,而您可以很容易地防止这种情况发生。施工结束后,他必须给锁打一次电话。他可能不知道这一点,忘记打电话,或者打两次。

更简单、更不容易出错的方法是将锁方法设为私有方法,并从构造函数中调用它。

但是,正如其他评论者所写的那样,最好是使用现有的图书馆。除了其他人提到的,Qt还有一个很好的QMutexLocker类。

我不相信它会比你现有的"简单"得多。您需要相互排除由多个进程修改的共享变量。您可能会遇到一种"只读"类型的情况,其中不需要互斥,但这无助于简化。

销毁互斥锁(当它超出范围时)可能是最好的方法,我已经看到许多线程库使用完全相同的方法。可移植工具库(PortableToolsLibrary,PTLib)是一个包含线程抽象的抽象库,当互斥对象超出范围时,它会释放互斥对象,但您仍然必须使用它们。但是,您还应该跟踪针对互斥体的调用和释放次数,以便在其他线程可用时向其发出信号。

此外,正如Bgie在回答中指出的那样,您确实需要保护您的代码永远不要相信其他程序员,包括你未来的自己。

但是,当范围剩下时释放锁的想法是一个很好的第一个一般实现,只需要一些额外的工作:)。

(根据Bgie的评论进行编辑)