まあ、recursive_mutex
... 再帰関数のためです!
一部のオペレーティング システムでは、同じミューテックスを 2 回ロックすると、システム エラーが発生する可能性があります (この場合、ロックが完全に解放され、アプリケーションがクラッシュし、実際にはあらゆる種類の奇妙で未定義の動作が発生する可能性があります)。
これを見てください(ばかげた例)
void recursivePusher(int x){
if (x>10){
return;
}
std::lock_guard<std::mutex> lock(m);
queue.push(x);
recursivePusher(x+1);
}
この関数は再帰的にインクリメントx
し、共有にプッシュしqueue
ます。上で説明したように、同じロックが同じスレッドによって 2 回ロックされることはありませんが、共有キューが複数のスレッドによって変更されていないことを確認する必要があります。
簡単な解決策の 1 つは、再帰関数の外側に位置指定を移動することですが、それができない場合はどうなるでしょうか。呼び出された関数が共有リソースをロックできる唯一の関数である場合はどうなりますか?
たとえば、呼び出し関数は次のようになります。
switch(option){
case case1: recursivly_manipulate_shared_array(); break;
case case2: recursivly_manipulate_shared_queue(); break;
case case3: recursivly_manipulate_shared_map(); break;
}
もちろん、3 つすべて (shred_Array、shared_map、shared_queue) をロックするわけではなく、そのうちの 1 つだけが変更されます。
解決策は使用することstd::shared_mutex
です:
void recursivePusher(int x){
if (x>10){
return;
}
std::lock_guard<std::recursive_mutex> lock(m);
queue.push(x);
recursivePusher(x+1);
}
同じスレッドがミューテックスを再帰的にロックする必要がない場合はstd::mutex
、例のように regular を使用する必要があります。
PS。あなたのスニペットでempty
は、と同じではありませんT::empty
。呼び出しは 再帰的に呼び出しdata.empty()
ません。empty