mutex::lock() 或unlock() 是否有任何惯用的显式用法?

问题描述 投票:0回答:3

使用

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()
永远不会被用户代码显式调用。

Q

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。因此,唯一合理的显式使用必须在调用
noexcept
(或
lock
)和
try_lock
之间仅涉及
unlock
方法。然而,由于
noexcept
只是建议性的,不具有任何承诺,因此这种使用是不安全的。 正确吗?

c++ multithreading c++11 locking mutex
3个回答
4
投票

lock_guard
并不是唯一需要在
lock
上调用
unlock
/
mutex
的事情。
unique_lock
lock
try_lock
condition_variable_any
都必须在互斥锁上工作。这只是标准类型。在这种情况下,友谊会带来紧密的耦合,从而成为一种障碍。


1
投票

当存在可以绑定资源生命周期的静态作用域时,可以(并且应该)使用 RAII,即,应在进入作用域时初始化资源,并在退出作用域时释放资源。

但是,在某些情况下,不存在这样的静态范围。 为了说明这一点,将变量视为资源。当存在可以将它们绑定到的静态作用域时,我们使用自动变量,但有时我们需要动态变量来控制它们的创建和销毁时间。

当我们使用

mutex
进行互斥时,也会发生同样的情况。考虑这个任务:

您的程序控制两个资源,它必须读取并执行一系列命令。可能的命令是:

  • 锁定资源#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
到达自己的指定点。可以通过使用初始化为
mutex
状态的
locked
并在
lock()
指定点之前放置
Q
操作以及在
unlock()
指定点之后放置
P
来满足此要求。可以很容易地验证此设置解决了问题。

这里

lock()
被放置在一个进程中,而
unlock()
被放置在另一个进程中,同样显然没有静态作用域可以包含它们,所以我们需要两者都可以独立访问。


0
投票

[在此处输入图像描述][1]

[1]:https://i.stack.imgur.com/E3jkR.jpg,解锁删除,观察系统YouTube。 Google 上的 Chrome、Google Play 商店可以解锁删除它的方法,显式删除标头。需要纯净版。真正在哪里所有观察到的Android系统摩托罗拉手机设备moto g power 5G (XT2311DL)都可以观察到它,请真正需要帮助,请禁止和解锁删除明确的,不是骗你的

© www.soinside.com 2019 - 2024. All rights reserved.