为什么 C++0x 或 Boost.Thread 中没有多个互斥体的作用域锁?

发布于 2024-08-30 15:39:21 字数 1533 浏览 2 评论 0原文

C++0x线程库或Boost.thread定义非成员变量模板函数,锁定所有锁以避免死锁。

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

虽然此函数有助于避免死锁,但标准不包括用于编写异常安全代码的关联作用域锁。

{
  std::lock(l1,l2);
  // do some thing
  // unlock li l2 exception safe
}

这意味着我们需要使用其他机制作为 try-catch 块来制作异常安全代码或自己在多个互斥锁上定义自己的作用域锁,甚至这样做

{
  std::lock(l1,l2);
  std::unique_lock lk1(l1, std::adopted);
  std::unique_lock lk2(l2, std::adopted);
  // do some thing
  // unlock li l2 on destruction of lk1 lk2
}

为什么该标准不包括对同一类型的多个互斥锁的作用域锁,例如

{
  std::array_unique_lock<std::mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

互斥体或元组的

{
  std::tuple_unique_lock<std::mutex, std::recursive_mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

设计是否有问题?


更新:标准描述

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

要求:每个模板参数类型都应满足互斥量要求,但调用 try_-lock() 可能会引发异常。 [ 注意:unique_lock 类模板在适当实例化后可以满足这些要求。 —尾注]

效果:通过对每个参数调用lock()、try_lock() 或unlock() 序列来锁定所有参数。调用顺序不应导致死锁,但在其他方面未指定。 [注:必须使用try-and-back-off等死锁避免算法,但未指定具体算法,以避免过度约束实现。 —尾注] 如果调用 lock() 或 try_lock() 引发异常,则应为通过调用 lock() 或 try_lock() 锁定的任何参数调用unlock()。


我已经接受答案了。我理解主要原因是没有足够的时间让C++0x Thread库变得更好。我希望TR2能包含更多的东西。

C++0x thread library or Boost.thread define non-member variadic template function that lock all lock avoiding dead lock.

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

While this function avoid help to deadlock, the standard do not includes the associated scoped lock to write exception safe code.

{
  std::lock(l1,l2);
  // do some thing
  // unlock li l2 exception safe
}

That means that we need to use other mechanism as try-catch block to make exception safe code or define our own scoped lock on multiple mutexes ourselves or even do that

{
  std::lock(l1,l2);
  std::unique_lock lk1(l1, std::adopted);
  std::unique_lock lk2(l2, std::adopted);
  // do some thing
  // unlock li l2 on destruction of lk1 lk2
}

Why the standard doesn't includes a scoped lock on multiple mutexes of the same type, as for example

{
  std::array_unique_lock<std::mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

or tuples of mutexes

{
  std::tuple_unique_lock<std::mutex, std::recursive_mutex> lk(l1,l2);
  // do some thing
  // unlock l1 l2 on destruction of lk
}

Is there something wrong on the design?


Updated: description from the standard

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);

Requires: Each template parameter type shall meet the Mutex requirements, except that a call to try_- lock() may throw an exception. [ Note: The unique_lock class template meets these requirements when suitably instantiated. —end note ]

Effects: All arguments are locked via a sequence of calls to lock(), try_lock(), or unlock() on each argument. The sequence of calls shall not result in deadlock, but is otherwise unspecified. [ Note: A deadlock avoidance algorithm such as try-and-back-off must be used, but the specific algorithm is not specified to avoid over-constraining implementations. —end note ] If a call to lock() or try_lock() throws an exception, unlock() shall be called for any argument that had been locked by a call to lock() or try_lock().


I have accept the answer. I understand that the main reason is because there is no enough time to make the C++0x Thread library better. I hope that TR2 will include much more things.

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

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

发布评论

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

评论(2

梦中的蝴蝶 2024-09-06 15:39:21

我认为通过提供 defer_lock_t (和 acquire_lock_t ),预期用法将像您的第二个示例一样,或者可能更像:

 std::unqiue_lock ul1(l1, std::deferred);
 std::unique_lock ul2(l2, std::deferred);
 std::lock(ul1, ul2);

这是异常安全的,而且都是好东西。

我当然不能假装了解设计师的想法,但我的猜测是他们正在努力提供一组最小的可移植、安全的原语。作用域多重锁类型只是锦上添花,如果在标准中需要指定和设计,或者在 boost.thread 中,则需要实现(当然最终标准必须关心)实施也是如此,看看导出发生了什么)。

I think that by providing defer_lock_t (and adopt_lock_t) the expectation is that usage will be like your second example, or probably more like:

 std::unqiue_lock ul1(l1, std::deferred);
 std::unique_lock ul2(l2, std::deferred);
 std::lock(ul1, ul2);

This is exception safe and all that good stuff.

I certainly can't pretend to know the minds of the designers, but my guess is they are making an effort to provide a minimal set of portable, safe, primitives. A scoped multiple lock type is just so much icing, and it's icing that if in the standard needs to be specified and designed, or in boost.thread, icing that needs to be implemented (and of course ultimately the standard has to be concerned about implementation too, look what happened with export).

锦欢 2024-09-06 15:39:21

构造一个锁定多个锁的对象并不能比单独锁定它们更能避免任何死锁。你不能同时锁定两个锁..除非你使用两个线程,这违背了这一点。即使您将它们放在同一个语句中也是如此。

Constructing one object that locks multiple locks does not avoid any deadlocks any more than locking them individually. You can't lock two locks simultaneously.. unless you use two threads, which kind of defeats the point. This holds true even if you put them in the same statement.

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