是否有任何惯用的显式使用mutex::lock()或unlock()
Is there any idiomatic explicit use of mutex::lock() or unlock()?
使用mutex
锁定代码关键区域的推荐方法是通过RAII,即
mutex_type mutex;
{ // start of critical region
std::lock_guard<mutex_type> lock(mutex); // first statement in critical region
// ... do critical stuff, may throw an exception
} // end of critical region
这样,当在关键区域内引发异常时,互斥锁仍将被解锁(由 std::lock_guard
的析构函数解锁)。但是,这样用户代码永远不会显式调用成员mutex::lock()
和mutex::unlock()
。
问:mutex::lock()
的主要惯用语(如果有的话)是什么?
我在问,否则让mutex::lock()
一个推广不良代码的公共成员(避免std::lock_guard
)是没有意义的。
编辑由于std::lock_guard<>
和std::mutex
都在同一标头中定义,因此std::mutex
可以轻松地与std::lock_guard<std::mutex
交朋友,并保护其lock()
和unlock()
方法:
class mutex // use only with lock_guard<mutex>
{
friend class lock_guard<mutex>; // support acquire-release semantic via RAII
friend class scoped_lock_guard<mutex>; // for supporting more complicated semantic,
// possibly remembering the mutex state.
// ...
protected:
void lock();
bool try_lock();
void unlock();
};
class raw_mutex // use if you absolutely must explicitly lock, try_lock, or unlock
: public mutex
{
public:
using mutex::lock;
using mutex::try_lock;
using mutex::unlock;
};
回答我的问题的一个论点很简单,使用mutex::lock()
的唯一异常安全方法是通过 RAII。因此,唯一合理的显式使用必须只涉及调用lock
(或try_lock
)和unlock
之间的noexcept
方法。但是,由于noexcept
只是暗示性的,并且没有任何承诺,因此这种使用是不安全的。Q 对吗?
lock_guard
并不是唯一需要在mutex
上调用lock
/unlock
的东西。 unique_lock
、lock
、try_lock
和condition_variable_any
都必须处理互斥体。 这只是标准类型。 在这种情况下,友谊引入了一种紧密的耦合,成为一种障碍。
当存在可以将资源的生存期绑定到的静态作用域时,可以使用 RAII,即资源应在进入作用域时初始化,并在退出作用域时释放。
但是,在某些情况下,没有这种静态范围。为了说明这一点,请将变量视为资源。当存在可以绑定它们的静态作用域时,我们使用自动变量,但有时我们需要动态变量来控制何时创建和销毁它们。
当我们使用 mutex
es 进行互斥时,也会发生同样的情况。请考虑以下任务:
您的程序控制两个资源,它必须读取和执行一系列命令。可能的命令包括:
- 锁定资源 #1 :
1>
- 锁定资源 #2 :
2>
- 解锁资源#1:
1<
- 解锁资源#2:
2<
- 将
x
写入资源 #1 :1x
- 将
x
写入资源 #2 :2x
您的程序可以期待类似1>
1a
2>
2b
1c
1<
2d
2<
,如果程序服从命令,则无法对 RAII 使用静态作用域(作用域必须部分重叠)。所以我认为这说明了需要显式锁定/解锁的一种情况。
至少还有一种可能的情况,因为
互斥并不是唯一可以使用mutex
的情况:它也可以用于同步。
考虑两个并行进程,P
和Q
,每个进程在其代码中都有一个指定的点。我们要求Q
在到达自己的点之前不能通过P
点。可以通过使用初始化为locked
状态的mutex
并将lock()
操作放在指定的Q
点之前,将unlock()
放在指定的P
点之后来满足。可以轻松验证此设置是否解决了问题。
在这里,lock()
放在一个进程中,unlock()
放在另一个进程中,显然没有静态范围可以包围它们,因此我们需要两者都可以独立访问。
- 尝试构建"lock-free"数据结构C++
- 为什么 c++11 std::lock 和 std::scoped_lock 至少需要 2 个参数?
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- DRD 报告"conflicting load" std::mutex::lock 上的错误
- 在 std::tie 中使用 std::weak_ptr::lock()
- std::lock_guard 怎么可能比 std::mutex::lock() 更快?
- std::mutex::lock() 产生奇怪(和不必要的)ASM 代码
- "lock cmpxchg"如何在装配中工作?
- std::lock 仍然导致死锁
- 在任何地方对C++中所有并行线程中的所有锁定和解锁实例使用相同的 std::mutex 和 lock 对象
- 我们是否需要对多线程 x32 系统使用 lock 来读取或写入 uint32_t 变量
- 使用Mutex,lock_guard,在课堂中正确地lock
- 当我调用lock()时,为什么std :: mutex会引发异常
- mutex.lock vs unique_lock
- 为什么在使用qt等待条件时不必包装lock/unlock语句
- 不同D3DPOOL实现的Direct3D VertexBuffer Lock()和Unlock()函数
- C++ use lock/unlock
- 触发 COM 事件时 Lock()/Unlock() 调用的目的是什么?
- 是否有任何惯用的显式使用mutex::lock()或unlock()
- PThread Mutex Lock & Unlock on Stack