【问题标题】:Why is the usage of mutex correct in C++?为什么在 C++ 中互斥锁的使用是正确的?
【发布时间】:2019-10-24 11:18:08
【问题描述】:

我之前被问过一个关于互斥锁的问题,代码工作正常,但我对这个结果感到困惑:

::std::mutex s_mutex;
void funcA()
{
    s_mutex.lock();

    printf( "funcA \n" );

    s_mutex.unlock();
}

void funcB()
{
    s_mutex.lock();

    funcA();

    printf( "funcB \n" );

    s_mutex.unlock();
}

int main()
{
    funcB();

    return 0;
}

它工作正常并打印出我没有预料到的内容:

funcA 
funcB 

但是为什么呢?这个函数在主线程中被调用,似乎调用了两次lock。

【问题讨论】:

  • 请注意,std::recursive_mutex 确实支持这种调用模式。
  • 感谢您的来信。我只是对这个案子感到困惑。

标签: c++ c++11 mutex


【解决方案1】:

来自std::mutex::lock()

如果lock 由已经拥有互斥锁的线程调用,行为未定义:例如,程序可能死锁。鼓励可以检测到无效使用的实现抛出带有错误条件resource_deadlock_would_occurstd::system_error,而不是死锁。

【讨论】:

  • 我也在funcB周围写了try catch代码,但没有异常(std::system_error)。
【解决方案2】:

正如@Quentin 所述,多次锁定一个线程中的std::mutex 会导致未定义的行为。要允许线程多次锁定互斥对象,可以使用std::recursive_mutex

递归互斥锁是一个可锁定的对象,就像互斥锁一样,但允许 同一个线程获得对互斥锁的多级所有权 对象。

这允许锁定(或尝试锁定)来自线程的互斥对象 已经锁定了它,获得了一个新级别的所有权 互斥对象:互斥对象实际上将保持锁定拥有 线程直到其成员解锁被调用的次数与此级别一样多 所有权。

【讨论】:

  • 感谢您的回答,我知道递归互斥锁,我很困惑为什么互斥锁在这种情况下看起来像递归
  • “看起来”是这里的关键词——仅仅因为它看起来工作正常,并不意味着它是;这只是意味着故障的症状不容易被发现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 2021-03-30
  • 2011-09-30
  • 1970-01-01
相关资源
最近更新 更多