4

想象一下,您有一个大函数可以锁定/解锁内部的互斥锁,并且您想将该函数分解为更小的函数:

#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);
}
4

2 回答 2

6

我应该如何在较小的函数中锁定/解锁互斥锁?

如果您的语义要求您的互斥锁在整个MyBigFunction()操作期间被锁定,那么您不能简单地解锁它并在函数中间重新锁定它。

我最好的选择是忽略较小DoSomethingWithBuffer...()函数中的互斥锁,只要求在互斥锁已被锁定的情况下调用这些函数。这应该不是问题,因为这些功能是私有的。


附带说明一下,您的互斥锁使用不正确:它不是异常安全的,并且您有不释放互斥锁的代码路径。如果您使用的是 C++03,您应该使用 C++11 的互斥锁和锁类或 boost 的等价物。在最坏的情况下,如果您不能使用 boost,请编写一个小的 RAII 包装器来保存锁。

于 2013-09-16T13:24:51.733 回答
2

通常,尽量将每个锁内的代码区域保持在最小(以避免争用),但避免解锁并立即重新锁定同一个互斥锁。因此,如果较小的函数不是互斥的,那么它们都应该使用它们自己的独立互斥量,并且仅在它们实际访问共享资源时才使用。

应该考虑的另一件事是使用 RAII 进行锁定和解锁(如在 C++11 中使用std::lock_guard<>),以便从锁定区域返回(直接或通过未捕获的异常)不会使您处于锁定状态。

于 2013-09-16T13:28:46.110 回答