【问题标题】:Creating a mutex locker class in C++在 C++ 中创建互斥锁柜类
【发布时间】:2012-08-16 06:06:28
【问题描述】:

这是我到目前为止所做的:

class mutexLocker
{
    private:
    /* Declaration of a Mutex variable `mutexA`. */
    pthread_mutex_t &mutexA;

    /* `mutexStatus` holds the return value of the function`pthread_mutex_lock `. 
    This value has to be returned to the callee so we need to preserve it in a class
    variable. */
    int             mutexStatus;

    /* We need to decide how to deal with the situation when one thread tries to lock then
    mutex repeatedly. If the mutex is of type recursive, then there won't be any problem for 
    sure, but otherwise the case may result in a deadlock. */
    pthread_t       calleeThreadId;

    public:
    /* Constructor attempts to lock the desired mutex variable. */
    mutexLocker (pthread_mutex_t argMutexVariable, pthread_t threadId) 
    : mutexA (argMutexVariable, calleeThreadId)
    {
        /* Return value is needed in order to know whether the mutex has been 
        successfully locked or not. */
        int mutexStatus = pthread_mutex_lock (&argMutexVariable);
    }

    /* Since the constructor can't return anything, we need to have a separate function
    which returns the status of the lock. */
    int getMutexLockStatus ()
    {
        return mutexStatus;
    }

    /* The destructor will get called automatically whereever the callee's scope ends, and
    will get the mutex unlocked. */
    ~mutexLocker ()
    {
        pthread_mutex_unlock (&mutexA);
    }
};

在 DIY 互斥锁类中应该提供哪些其他功能?

【问题讨论】:

  • 您是否有理由自己实现而不是使用 Boost 或 C++11 标准库中提供的锁类?
  • “在 DIY 互斥锁类中应该提供哪些其他功能?”是一个非常主观的问题,“可能会引发辩论、争论、投票或扩展讨论”——因此投票结束是非建设性的。
  • @JoachimPileborg 我不知道 C++ 标准有任何互斥锁类!我之前确实在谷歌上搜索过。我再看看。
  • @paxdiablo 我应该如何修改这个问题以使其具体化?
  • 参见例如std::lock_guard。这些在 C++11 标准中是新的,所以如果你有一个旧的编译器,它可能不支持它。 VC++ 2010 应该有它,还有 GCC 4.4。

标签: c++ multithreading pthreads mutex


【解决方案1】:

我完全同意 Slavik81 的 cmets 关于不创建您没有用例的功能的观点。

尽管如此,引用锁类的 Boost 实现可能是了解其接口的共同要求的一个很好的起点:http://www.boost.org/doc/libs/1_42_0/doc/html/thread/synchronization.html#thread.synchronization.locks

在标准C++11方面引入std::lock_guardhttp://en.cppreference.com/w/cpp/thread/lock_guard

【讨论】:

  • 谢谢你的链接,我去看看。但是重建这个学习不是很好吗?重建它不会有助于理解线程的基础知识吗?
  • 为您自己的个人理解编写一个没有害处,但除此之外,如果您使用 C++11,我通常会坚持使用std::lock_guard,否则boost::lock_guard,因为它经过了良好的测试并且很常见明白了。
【解决方案2】:

你有点倒退了。你编写代码来解决你面临的问题。不要编写代码来解决你没有的问题。 “You aren't gonna need it”是个好原则。

除非您有可以用它们解决的问题,否则不应提供其他功能。鉴于您没有提到任何问题,我认为您没有这样的问题。因此,不应添加其他功能。

【讨论】:

    【解决方案3】:

    首先,Graeme 和 Slavik81 的答案都非常好 (+1)。

    现在,至于要添加的内容:

    • 您可能需要额外的错误支持,具体取决于您处理错误的方式。例如,如果您的团队在锁定失败时抛出异常,则该类可以创建并抛出异常。
    • 作为诊断,您可能希望验证测试的客户端获取成功(例如,如果他们从未验证锁定成功,则在 dtor 中使用 assert)。
    • 您可能需要“重试”采集功能。最好在抛出异常之前重试,imo。就我个人而言,如果EBUSY -- 不要持有长锁,我只是认为这是程序员的错误!
    • 还将您的pthread_mutex_t 隐藏在课堂上——禁止复制、分配等。把它交给你的储物柜。
    • 一些客户可能需要一种简单的方法来测试成功,而不是评估状态。取决于你如何使用它。
    • 如果您没有获得锁,请不要在 dtor 中解锁
    • 检查解锁结果。确定这种情况下的错误处理。

    也许更重要的是 - 确定要删除的内容

    • 禁止复制。明确删除复制 ctor 表达了意图。
    • 删除operator= -- 表达意图。
    • 删除动作
    • calleeThreadId:除非你觉得有用,否则删除。具体来说,考虑一下您将如何实际实施您提出的这种错误检测——储物柜似乎是存放数据的错误位置,imo。我更喜欢让这些储物柜保持最小、专注和简单。
    • extra mile:防止堆分配;例如删除运算符 new/delete 的主要变体。
    • 如果您不重试,则状态可能为const
    • threadID,如果你决定保留它,也可以是const

    最后,通过引用传递互斥锁(虽然我认为这是一个错字)。

    【讨论】:

    • 你说:"calleeThreadId - 除非你觉得有用,否则删除。" 我认为这将有助于检测是否对非递归互斥体进行了递归调用。如果您能详细解释其余要点,我将不胜感激。你的意思是我不应该将函数参数 mutex 复制到类变量 mutex 中?
    • 但是如果我们安全地复制/分配有什么问题呢?我没有安全地完成它吗?
    • @AnishaKaul 正如你所写的,它们(隐含地)不可能复制/分配——所以此时它是安全的。但是,如果它们确实存在,则会导致不平衡——如果按照程序的流程,mutexStatus 将被覆盖,并且复制时会出现太多解锁(因为隐式复制不会锁定——这也可能导致死锁,取决于互斥体类型)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-31
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2018-05-23
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多