C++ 11两个关键部分可以使用嵌套锁定guard?

发布于 2025-02-07 17:41:14 字数 529 浏览 2 评论 0原文

如果我有两个关键部分,并且我进行了两个相应的静音以保护它们。(我认为有必要精确控制何时锁定,因为它们在不同的时间和场景中使用,Q1是:真的是吗?) 例如:

bool a;//ignore atomic_bool, because in actual, the data structure is more complex
mutex mut_a;//for threadsafe of a
bool b;
mutex mut_b;//for threadsafe of b

我需要实现这种逻辑:

if (lock_guard<mutex> lck(mut_a);a) { do something...
}
else {
    if (lock_guard<mutex> lck(mut_b);b) { do something...
  }
}

如Seave,使用Lock_Guard(Mutex)嵌套,Q2是否正确且螺纹安全?

If I have two critical sections, and I make two corresponding mutex to protect each of them.(I think it is necessary to precisely control when to lock because they use in different times and scenario, Q1:is it really so?)
For example:

bool a;//ignore atomic_bool, because in actual, the data structure is more complex
mutex mut_a;//for threadsafe of a
bool b;
mutex mut_b;//for threadsafe of b

And I need to implement this kind of logic:

if (lock_guard<mutex> lck(mut_a);a) { do something...
}
else {
    if (lock_guard<mutex> lck(mut_b);b) { do something...
  }
}

As seen, lock_guard(mutex) is used nested, Q2is it proper and threadsafe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月隐月明月朦胧 2025-02-14 17:41:15

我认为这里的一个问题是,

if (bool x = true)
{
    // x is in scope
}
else
{
    // x is STILL in scope!
    x = false;
}

因此mut_a上的第一个锁仍然保存在else块中。这可能是您的意图,但我认为这不是一个最佳的写作方法,如果是这样。

另外,如果在b的关键部分中

I think a problem here is that

if (bool x = true)
{
    // x is in scope
}
else
{
    // x is STILL in scope!
    x = false;
}

So the first lock on mut_a is still held in the else block. Which might be your intention, but I would consider this not an optimal way to write it for readability if that were so.

Also, if it is important that !a in the critical section of b you DO need to keep the lock on a.

执笏见 2025-02-14 17:41:15

该代码本质上不是不安全的。但是,...

正如另一个答案中已经提到的那样,您需要考虑静音也锁定在其他分支中:

if (lock_guard<mutex> lck(mut_a);a) { do something...
     // mut_a is locked
} else {
    if (lock_guard<mutex> lck(mut_b);b) { do something...
        // mut_a and mut_b are locked
    }
}

也许这是针对的。如果不是,那是错误的。

此外,您需要谨慎一次锁定多个静音。当其他地方以不同的顺序锁定它们时,会有一个死锁:

 {
     lock_guard<mutex> lock_b(mut_b);
     lock_guard<mutex> lock_a(mut_a);
     // do something
 }

您的代码锁mut_a,并且仅在能够在mut_b上获得锁后才会发布。此代码锁定mut_b,并且仅在能够在mut_a上获得锁后才会发布。

为了避免这样的僵局,您可以使用 std :: scoped_lock 使用多个静音并使用一些僵局避免算法。

The code is not inherently unsafe. However, ...

As already mentioned in another answer, you need to consider that the mutex is locked also in the else branch:

if (lock_guard<mutex> lck(mut_a);a) { do something...
     // mut_a is locked
} else {
    if (lock_guard<mutex> lck(mut_b);b) { do something...
        // mut_a and mut_b are locked
    }
}

Maybe this is intended. If it is not then its wrong.

Moreover you need to be careful with locking multiple mutexes at once. When elsewhere you lock them in different order there will be a deadlock:

 {
     lock_guard<mutex> lock_b(mut_b);
     lock_guard<mutex> lock_a(mut_a);
     // do something
 }

Your code locks mut_a and only releases it after it was able to acquire a lock on mut_b. This code locks mut_b and only releases it after it was able to acquire a lock on mut_a.

To avoid such deadlock you can use std::scoped_lock that takes multiple mutexes and uses some deadlock avoidance algorithm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文