如果在锁定互斥锁之前将其解锁,可以吗?

时间:2019-07-28 00:05:25

标签: c++ multithreading locking mutex

我以前写过一些代码,但是我意识到它的代码风格很糟糕,所以我进行了更改。

我更改了if块内部的A.unlock。我知道,如果永不运行,则该线程将解锁互斥体,互斥体不属于自身,然后它将返回未定义的行为。 我的问题是,如果返回未定义的行为,这里的逻辑是否仍然有效?因为如果线程t1没有锁,则t1解锁互斥锁A将返回未定义行为,并且互斥锁仍将由保持它正确的线程持有吗?并且它不会影响此代码中的其他逻辑。 我的旧代码的工作原理与将解锁部分放入if块中的工作原理相同。所以这就是为什么我好奇如何工作。

mutex A;
if(something)
{
A.lock();
}
A.unlock();

4 个答案:

答案 0 :(得分:2)

您应该考虑使用std::lock_guard

mutex A;
if (something)
{
    lock_guard<mutex> lock(A);
}

答案 1 :(得分:2)

在互斥锁上调用unlock时,该互斥锁必须归当前线程所有,否则行为未定义。未定义的行为意味着一切都可能发生,包括程序似乎正常运行,程序崩溃或其他地方的内存损坏以及直到以后才发现问题。

通常不直接使用互斥锁;其他标准类之一(例如std::unique_lockstd::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.
}