我有类似的代码:
do {
lock_guard<mutex> lck(globalMtx);
auto itr = someMap.end();
for (/*conditions*/){
//do stuff with itr and someMap
// if a certain condition is met, we exit function with a return
// globalMtx needs to be unlocked at that time
}
if (itr == someMap.end()){
// I need to unlock the globalMtx here
globalMtx.unlock()
// A command is sent to modify someMap before we try again
this_thread::sleep_for( chrono::seconds( 5 ) );
} else {
break;
}
} while (true);
正如你在if范围中看到的,我需要解锁globalMtx,以便我可以修改&#34; someMap&#34;然后再次通过它。我已经阅读了许多线程/论坛/使用mutex.lock()/ unlock()手动锁定互斥锁是一个坏主意,通常不再使用c ++ 11或更高版本。
那么在这种情况下我可以根据需要控制互斥锁,同时仍然可以防止任何离开示波器的情况使互斥锁被锁定?
答案 0 :(得分:8)
不,在这种情况下,您不应直接致电std::mutex::unlock()
,因为std::lock_guard
析构函数会再次调用std::mutex::unlock()
,这将导致UB。您可以使用std::unique_lock代替std::lock_guard
轻量级,但允许您在其上调用unlock()
:
std::unique_lock<mutex> lck(globalMtx);
...
lck.unlock(); // lck object is aware that globalMtx is released and would do nothing in it's dtor after this
答案 1 :(得分:2)
是的,这是一个坏主意,因为lock_guard
在销毁互斥锁时仍会解锁互斥锁,因此互斥锁最终会被解锁两次。这会导致未定义的行为(即如果你很幸运就会崩溃)。
相反,请使用std::unique_lock
。这有一个unlock()
方法,它不仅可以调用底层互斥锁的unlock
方法,还可以保证unique_lock
对象不会再次解锁互斥锁。
答案 2 :(得分:1)
写一个像lock_guard一样的包装器,它跟踪互斥锁是否被保持,只有在被保持时才解锁。包装器应该同时具有解锁和重新锁定(如果已经锁定,则为无操作) ..