Jer*_*hoy 5 c++ mutex locking exception c++11
从CPPReference来看,std::mutex如果锁不会导致死锁,则不会明确表示锁定函数不会抛出.
PThread的锁只有死锁错误.我不知道窗口的线程实现.我也不知道它们是否是用作std::thread/的后端的其他线程实现std::mutex.
所以我的问题是"我是否应该编写我的代码,好像有时候,没有特殊原因,锁定可能会失败?".
我实际上需要在一些noexcept方法中锁定一个互斥锁,我想确保它们是noexcept.
所述std::mutex::lock()成员函数未声明为noexcept和从部分30.4.1.2互斥类型的C++ 11标准的(草案n3337),第6:
表达式
m.lock()应格式良好并具有以下语义:
- ...
- 抛出:
system_error需要例外时(30.2.2).- 错误条件:
operation_not_permitted- 如果线程没有执行操作的权限.resource_deadlock_would_occur- 如果实现检测到会发生死锁.device_or_resource_busy- 如果互斥锁已被锁定且无法阻止.
这意味着任何使用的函数mutex::lock()都不能被标记noexcept,除非该函数能够处理异常本身并阻止它传播给调用者.
我无法评论这些错误情况发生的可能性,但是std::mutex与resource_deadlock_would_occur(和可能被抛出)相关的错误表示代码中的错误而不是运行时失败,因为如果线程尝试此错误可能会引发此错误锁定std::mutex它已经拥有的.从第30.4.1.2.1节类互斥,第4节:
[注意:如果拥有互斥对象的线程在该对象上调用lock(),则程序可能会死锁.如果实现可以检测到死锁,则可以观察到resource_deadlock_would_occur错误情况. - 尾注]
通过选择std::mutex锁定类型,程序员明确地声明同一线程锁定mutex它已经锁定的尝试是不可能的.它是一个合法的执行线程来重新锁定a mutex然后a std:recursive_mutex是更合适的选择(但改为a recursive_lock并不意味着该lock()函数是免费的异常).
在 POSIX 系统上,std::mutex可能会使用 POSIX 互斥体来实现,并std::mutex::lock()最终委托给pthread_mutex_lock(). 尽管 C++ 互斥体不需要使用 POSIX 互斥体来实现,但 C++ 标准多线程的作者似乎已经根据 POSIX 错误条件对可能的错误条件进行了建模,因此检查这些可能具有指导意义。正如用户 hmjd 所说,该方法允许的 C++ 错误条件lock是 operation_not_permitted、resource_deadlock_would_occur和device_or_resource_busy。
POSIX 错误条件是:
EINVAL:如果 POSIX 特定的锁优先级功能被误用,如果您仅使用标准 C++ 多线程设施,则永远不会发生这种情况。这种情况可能对应于operation_not_permittedC++ 错误代码。EINVAL:如果互斥体尚未初始化,这将对应于损坏的std::mutex对象、使用悬空引用或指示程序错误的其他一些未定义行为。EAGAIN:如果互斥锁是递归的并且递归太深。这不可能发生在 a 上std::mutex,但可能会发生在 a 上std::recursive_mutex。这似乎与device_or_resource_busy错误条件相对应。EDEADLK:如果由于线程已经持有锁而发生死锁。这将对应于resource_deadlock_would_occurC++ 错误代码,但会指示程序错误,因为程序不应尝试锁定std::mutex它已经锁定的 a(std::recursive_mutex如果您确实想这样做,请使用 a)。C++operation_not_permitted错误代码显然旨在与 POSIXEPERM错误状态相对应。该pthread_mutex_lock()函数从不给出此状态代码。但是描述该函数的 POSIX 手册页也描述了该函数,如果您尝试解锁尚未锁定的锁,pthread_mutex_unlock()则可能会给出该函数。EPERM也许 C++ 标准作者operation_not_permitted错误地阅读了 POSIX 手册页而将其包含在内。由于 C++ 没有锁“权限”的概念,因此很难看出任何正确构造和操作的锁(根据 C++ 标准使用,不调用任何未定义的行为)如何导致EPERM和operation_not_permitted。
device_or_resource_busyC++17 不允许,这表明它在实践中从未真正发生过,并且将其包含在 C++11 中是一个错误。
总而言之,唯一std::mutex::lock()可能引发异常的情况表明程序错误。因此可以合理地假设该方法“从不”抛出异常。