如果我在锁定互斥锁之前解锁它可以吗?

Is that OK if I unlock a mutex before I lock it?

我之前写过一些代码,但我发现它的代码风格很糟糕,所以我改变了它。

我更改了 if 块内的 A.unlock。我知道如果 if never 运行 那么这个线程将解锁不属于它自己的互斥锁,然后它会 return 一个未定义的行为。 我的问题是,如果它 return 是未定义的行为,这里的逻辑是否仍然有效?因为如果线程 t1 没有锁,t1 解锁互斥量 A 将 return 取消定义行为并且互斥量仍将由持有它的线程持有,对吗?并且不会影响这段代码中的其他逻辑。 我的旧代码与我将解锁部分放在 if 块中一样。所以这就是为什么我很好奇这是如何工作的。

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

你应该考虑使用 std::lock_guard :

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

在互斥量上调用 unlock 时,互斥量必须由当前线程拥有,否则行为未定义。未定义的行为意味着任何事情都可能发生,包括程序 运行 正确显示、程序崩溃或其他地方的内存损坏以及问题直到后来才可见。

通常不直接使用互斥量;其他标准之一 类 (如 std::unique_lock or std::lock_guard 用于管理它。那么您就不必担心解锁互斥锁。

这是一个 undefined behavior 来解锁一个你还没有锁定的 mutex。它可能会在某些情况下工作很多次,但总有一天它会崩溃并表现不同。

你可以在你的情况下使用 lock_guard 而忘记 lock/unlock

std::lock_guard<std::mutex> lock(A);

ISO C++ 标准在 [thread.mutex.requirements.mutex](我强调的)中对此事有这样的说法:

The expression m.unlock() shall be well-formed and have the following semantics:

Requires: The calling thread shall own the mutex.

这意味着你所做的是违反标准的,因此是未定义的。它 可能 有效,或者它可能会在播放 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.
}