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之类的死锁避免算法,但未指定特定算法以避免过度约束实现。 -end note]如果对lock()或try_lock()的调用抛出异常,则应对通过调用lock()或try_lock()锁定的任何参数调用unlock()。
我接受了答案。我知道主要原因是因为没有足够的时间来使C ++ 0x Thread库更好。我希望TR2会包含更多内容。
答案 0 :(得分:3)
我认为通过提供defer_lock_t(和adopt_lock_t),期望用法就像你的第二个例子,或者更像是:
std::unqiue_lock ul1(l1, std::deferred);
std::unique_lock ul2(l2, std::deferred);
std::lock(ul1, ul2);
这是异常安全和所有好东西。
我当然不能假装知道设计师的想法,但我猜他们正在努力提供一套最小的便携,安全,原始的设备。范围内的多重锁定类型只是如此多的结冰,如果在标准中需要指定和设计,或者在boost.thread中,需要实施的结冰(当然最终标准必须关注)实施也是如此,看看出口发生了什么)。
答案 1 :(得分:-1)
构造一个锁定多个锁的对象不会避免任何死锁,只能单独锁定它们。你不能同时锁定两个锁..除非你使用两个线程,哪种方式会失败。即使你把它们放在同一个声明中也是如此。