16

thisによると、unique_locka を宣言することで再帰ロックに使用できstd::unique_lock<std::recursive_mutex>、実際には正常にコンパイルされます。

ただし、コード (gcc 4.8.2 および 4.9.0) を調べると、ロック メソッド自体を実装するのではなく、ロック メソッド自体を実装しているようにunique_lock見えます。_Mutex.lock

  void
  lock()
  {
if (!_M_device)
  __throw_system_error(int(errc::operation_not_permitted));
else if (_M_owns)
  __throw_system_error(int(errc::resource_deadlock_would_occur));
else
  {
    _M_device->lock();
    _M_owns = true;
  }

明らかに、これによりミューテックスの再帰的ロックが防止され、実際、再帰的にロックしようとするとresource_deadlock_would_occur例外がスローされます。

ここに何かが欠けていますか、これはバグですか、それともunique_lockのドキュメントが間違っていますか?

ティア!!!

4

1 に答える 1

31

よくある間違いは、 と を混同するmutexことlockです。Amutexは、スレッド間で共有できるオブジェクトです (それ以外の場合は役に立ちません)。ただし、ロック自体はスレッドセーフなオブジェクトではありません。スレッド間で共有しないでください。通常、スタック上のローカル オブジェクトです。例えば:

void foo()
{
     std::unique_lock<std::mutex> lk(mut);  // mut comes from some other scope
     // mut locked here
     // ...
}    // mut unlocked here

上記の例でfoo()は、 が再帰的に呼び出された場合、再帰的にロックするため、未定義の動作が発生しますmut。再帰のたびに、新しいunique_lockものを取得します。したがって、unique_lockは再帰を認識しません。本当に再帰的に呼び出す必要がある場合foo()は、再帰的ミューテックスを使用する必要があります。次に例を示します。

void foo()
{
     std::unique_lock<std::recursive_mutex> lk(mut);  // mut comes from some other scope
     // mut locked here
     // ...
}    // mut unlocked here

はい、使用できますstd::unique_lock<std::recursive_mutex>。はい、実装は正しいです。

于 2014-12-23T19:26:50.600 に答える