我以前写过一些代码,但是我意识到它的代码风格很糟糕,所以我进行了更改。
我更改了if块内部的A.unlock。我知道,如果永不运行,则该线程将解锁互斥体,互斥体不属于自身,然后它将返回未定义的行为。 我的问题是,如果返回未定义的行为,这里的逻辑是否仍然有效?因为如果线程t1没有锁,则t1解锁互斥锁A将返回未定义行为,并且互斥锁仍将由保持它正确的线程持有吗?并且它不会影响此代码中的其他逻辑。 我的旧代码的工作原理与将解锁部分放入if块中的工作原理相同。所以这就是为什么我好奇如何工作。
mutex A;
if(something)
{
A.lock();
}
A.unlock();
答案 0 :(得分:2)
您应该考虑使用std::lock_guard
:
mutex A;
if (something)
{
lock_guard<mutex> lock(A);
}
答案 1 :(得分:2)
在互斥锁上调用unlock时,该互斥锁必须归当前线程所有,否则行为未定义。未定义的行为意味着一切都可能发生,包括程序似乎正常运行,程序崩溃或其他地方的内存损坏以及直到以后才发现问题。
通常不直接使用互斥锁;其他标准类之一(例如std::unique_lock
或std::lock_guard
)用于管理它。这样您就不必担心解锁互斥锁了。
答案 2 :(得分:0)
这是undefined behavior来解锁您尚未锁定的mutex
。在某些情况下,它可能会工作很多次,但有一天,它会破裂并表现出不同的行为。
您可以在案件中使用lock_guard
,而不必担心锁定/解锁
std::lock_guard<std::mutex> lock(A);
答案 3 :(得分:0)
ISO C ++标准对此有这样的说法,[thread.mutex.requirements.mutex]
(我强调):
表达式
m.unlock()
的格式应正确,并具有以下语义:要求:调用线程应拥有互斥体。
这意味着您正在执行的操作违反了标准,因此未定义。它可能有效,或者可能在播放derisive_maniacal_laughter.mp3
文件时删除所有文件:-)
底线,不要这样做。
我也不会将unlock
放入循环中,因为现代C ++具有用于处理资源自动释放的更高级别的机制。在这种情况下,它是一个锁卫:
std::mutex mtxProtectData; // probably defined elsewhere (long-lived)
: : :
if (dataNeedsChanging) {
std::lock_guard<std::mutex> mtxGuard(mtxProtectData);
// Change data, mutex will unlock at brace below
// when mtxGuard goes out of scope.
}