保持 std::mutex 锁定/解锁公开的基本原理
Rationale to keep std::mutex lock/unlock public
我的问题很简单。在 C++11 年,我们有std::mutex
、std::lock_guard
和std::unique_lock
.
使用这些类的常用方法是通过任何锁锁定std::mutex
。这可以防止由于异常引发而导致互斥锁泄漏:
{
std::lock_guard<std::mutex> l(some_mutex);
//Cannot leak mutex.
}
为什么std::mutex::lock
和std::mutex::unlock
是公开的?这需要不正确的使用:
{
some_mutex.lock();
//Mutex leaked due to exception.
some_mutex.unlock();
}
让std::lock_guard
和std::unique_lock
成为std::mutex
的朋友并将std::mutex
锁定操作设为私有不是更安全吗?这将防止不安全的使用。
我能猜到这个设计的唯一原因是,如果我有自己的锁,它就不能与std::mutex
一起使用,因为我将无法std::mutex
成为自己的锁朋友。这是公开这些成员函数的主要原因吗?
N2406 中记录了此设计决策的基本原理:
与 boost 不同,互斥体具有 lock() 的公共成员函数, 解锁(),等等。这对于支持主要目标之一是必要的: 用户定义的互斥锁可以与标准定义的锁一起使用。如果有 如果没有用户定义的互斥锁要实现的接口,则 标准定义的锁无法与用户通信 定义的互斥锁。
在撰写本文时,boost::mutex 只能使用 boost::scoped_lock 锁定和解锁。
所以你现在可以写my::mutex
,只要你提供成员lock()
和unlock()
,你的my::mutex
和std::mutex
一样是一等公民。 您的客户可以使用std::unique_lock<my::mutex>
就像他们可以使用std::unique_lock<std::mutex>
一样容易,即使std::unique_lock
不知道my::mutex
是什么。
一个激励人心的现实生活中my::mutex
的例子是现在在C++1y(我们希望y == 4)标准草案中提出的std::shared_mutex
。 std::shared_mutex
具有用于独占模式锁定和解锁的成员lock()
和unlock()
。 当客户端按预期使用std::unique_lock<std::shared_mutex>
时,它会与std::unique_lock
交互。
以防万一您可能认为shared_mutex
可能是唯一可以使用此通用接口的其他激励互斥锁,这是另一个真实世界的示例::-)
template <class L0, class L1>
void
lock(L0& l0, L1& l1)
{
while (true)
{
{
unique_lock<L0> u0(l0);
if (l1.try_lock())
{
u0.release();
break;
}
}
this_thread::yield();
{
unique_lock<L1> u1(l1);
if (l0.try_lock())
{
u1.release();
break;
}
}
this_thread::yield();
}
}
这是如何一次锁定(以异常安全的方式)两个 BasicLockable,而不会有死锁危险的基本代码。 尽管有许多相反的批评,但这段代码非常有效。
请注意上面代码中的行:
unique_lock<L0> u0(l0);
该算法不知道L0
是什么类型。 但只要它支持lock()
和unlock()
(好吧,也try_lock()
),一切都很酷。 L0
甚至可能是unique_lock
的另一个实例,也许是unique_lock<my::mutex>
,甚至可能是unique_lock<std::shared_mutex>
,甚至可能是std::shared_lock<std::shared_mutex>
。
这一切都是有效的。 而这一切都是因为除了商定的lock()
和unlock()
的公共界面之外,std::unique_lock
和std::mutex
之间没有亲密关系。
正如Jerry Coffin指出的那样,我们只能在没有实际委员会成员参与的情况下进行推测,但我的猜测是,他们设计的界面具有灵活性,并且能够以自己的方式扩展它们。 与其让每个潜在的类都成为std::mutex
的朋友,不如公开接口来执行所需的操作,允许某人(例如提升贡献者)出现并找到一种新的更好的方法来使用它。 如果接口被隐藏,那是不可能的。
- 我应该在锁定TBitmap画布后解锁它吗
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- c++ 为什么我不应该从不同的线程解锁互斥锁
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- "data race"(不是真的)在通知条件变量并解锁关联的互斥锁后
- 程序输入密码并解锁窗口7,8,10
- 在通知之前完成手动解锁
- STD :: Mutex如何在不同的线程中解锁
- 如何使用单个解锁方法(可称为读取器或写入器)实现C++读写器锁?
- 如何在C 中自动汇总日志消息并自动解锁互斥X
- 如果我们已经手动解锁了unique_lock,那么破坏时会解锁吗?
- 正在解锁手动未定义/不良设计的锁定guard
- 从C 运行代码后解锁绑定(在R中)的问题
- 在功能返回之前,可以解锁Mutex会增加并发
- 当互斥锁解锁时,它会notify_all或notify_one
- 如何确保在C ++中解锁储物柜?哪种解决方案更好
- 我应该如何在一个功能中锁定wxMutex,并在另一个功能中将其解锁
- mutex::lock() 检查一次解锁状态是否已经被另一个线程锁定?
- 保持 std::mutex 锁定/解锁公开的基本原理
- C++ 在调用 std::unique_lock 等待之前解锁 std::mutex