2014-04-18 44 views
1

我是C++新手。在学习线程是如何工作的时候,我发现在开始时调用WaitForSingleObject(x)并在最后调用ReleaseMutex(x)是非常烦人的。所以我写了一个课程来为我做这件事,但我不确定这个影响,我做对了。奇迹是否有更简化的方法来实现?下面是我如何做到这一点:C++:如何简化线程锁定?

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

这是别人通常怎么办线程锁的方式吗?

+2

为什么不使用[线程支持库](http://en.cppreference.com/w/cpp/thread)中的标准成语?这应该简化你的代码! –

+0

使用'std :: lock_guard','std :: thread',如果你必须使用'std :: mutex'。 – noobProgrammer

回答

1

我不相信它会比你拥有的“更简单”。您需要相互排除许多进程正在修改的共享变量。你可能有一个“只读”类型的情况下,不需要互斥锁,但这不会帮助你简化。

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

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

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

(编辑由于Bgie的评论)

+0

你没有注意到代码中的错误。该类不记录要锁定的呼叫数量,并始终释放一次。 – Bgie

+0

嗯,经验人总会发现一些问题,但不是小菜鸟。 当我编写这个测试程序时,我在想这个场景如下所示: TestMutex类具有可供所有线程访问的共享资源,但是当任何线程正在修改它时,其他线程都不应该能够获取此共享资源,直到修改完成。 – tongko

+0

当我说noob看不到问题时,我真的想问为什么我们需要跟踪呼叫和发布的数量? – tongko

2

其实,你让你的类API的消费者滥用它,当你可以很容易地防止这种情况。 施工后他必须调用锁定一次。他可能不知道这一点,忘记打电话或打电话两次。

简单且不太容易出错的方法是将锁定方法设置为private,并从构造函数中调用它。

但是,正如其他评论者所写,最好的是使用现有的库。 除了别人提到的之外,Qt还有一个不错的QMutexLocker类。

+0

现在我明白了这个问题。感谢您的好建议。 – tongko