想象一下,你有一个很大的功能来锁定/解锁内部的互斥锁,你想把这个功能分解成更小的功能:
#include <pthread.h>
class MyClass : public Uncopyable
{
public:
MyClass() : m_mutexBuffer(PTHREAD_MUTEX_INITIALIZER), m_vecBuffer() {}
~MyClass() {}
void MyBigFunction()
{
pthread_mutex_lock(&m_mutexBuffer);
if (m_vecBuffer.empty())
{
pthread_mutex_unlock(&m_mutexBuffer);
return;
}
// DoSomethingWithBuffer1();
unsigned char ucBcc = CalculateBcc(&m_vecBuffer[0], m_vecBuffer.size());
// DoSomethingWithBuffer2();
pthread_mutex_unlock(&m_mutexBuffer);
}
private:
void DoSomethingWithBuffer1()
{
// Use m_vecBuffer
}
void DoSomethingWithBuffer2()
{
// Use m_vecBuffer
}
private:
pthread_mutex_t m_mutexBuffer;
std::vector<unsigned char> m_vecBuffer;
};
如何在较小的函数内部锁定/解锁互斥锁?
我应该首先解锁互斥锁,然后直接将其锁定,最后在返回之前将其解锁吗?
void DoSomethingWithBuffer1()
{
pthread_mutex_unlock(&m_mutexBuffer);
pthread_mutex_lock(&m_mutexBuffer);
// Use m_vecBuffer
pthread_mutex_unlock(&m_mutexBuffer);
}
答案 0 :(得分:5)
如何在较小的函数内部锁定/解锁互斥锁?
如果您的语义要求在整个MyBigFunction()
操作期间锁定您的互斥锁,那么您不能简单地将其解锁并在函数中间重新锁定它。
我最好的选择是忽略较小DoSomethingWithBuffer...()
函数中的互斥锁,并且只需要在互斥锁已被锁定的情况下调用这些函数。这应该不是问题,因为这些功能是私有的。
另一方面,您的互斥锁使用情况不正确:它不是异常安全的,并且您有代码路径,您不会释放互斥锁。如果您使用的是C ++ 03,则应该使用C ++ 11的互斥锁和锁类或者升级等价物。在最坏的情况下,如果你不能使用boost,请写一个小的RAII包装器来保持锁定。
答案 1 :(得分:2)
通常,尽量将每个锁中的代码区域保持在最小(以避免争用),但要避免解锁并立即重新锁定相同的互斥锁。因此,如果较小的函数不是互斥的,那么它们都应该使用它们自己的独立变量,并且只有在它们实际访问共享资源时才会使用。
应该考虑的另一件事是使用RAII进行锁定和解锁(如在带有std::lock_guard<>
的C ++ 11中),以便从锁定区域(直接或通过未捕获的异常)返回不会离开你处于锁定状态。