gpt4 book ai didi

c++ - 为什么互斥锁可以在 C++ 中锁定两次而不解锁?

转载 作者:行者123 更新时间:2023-12-01 14:03:44 25 4
gpt4 key购买 nike

int main(){

std::mutex mut;
mut.lock();
cout<<"1111\n";
mut.lock();
cout<<"2222\n";
return 0;
}
为什么这段代码可以工作并输出 2222 ?它不应该在第二个 lock() 处阻塞吗?在互斥锁源码中,操作锁抛出异常。它不应该阻塞并等待吗?我用 try{...}catch(exception& e){}捕获此异常,但它不起作用。
    void
lock()
{
int __e = __gthread_mutex_lock(&_M_mutex);

// EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
if (__e)
__throw_system_error(__e);
}

最佳答案

这不可以。您的代码具有未定义的行为。
来自 cppreference :

If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.


继续阅读,您可能会觉得调用 lock在同一个线程上总是会触发异常:

Exceptions

Throws std::system_error when errors occur, including errors from theunderlying operating system that would prevent lock from meeting itsspecifications. The mutex is not locked in the case of any exceptionbeing thrown.


但是,调用 lock 时不一定有异常(exception)。在同一个线程中。仅当实现可以检测到这种无效使用并且仅当实现足够友好以实际引发异常时。
研究标准 we find :

1 The class mutex provides a non-recursive mutex with exclusiveownership semantics. If one thread owns a mutex object, attempts byanother thread to acquire ownership of that object will fail (fortry_­lock()) or block (for lock()) until the owning thread hasreleased ownership with a call to unlock().

2 [Note: After a thread A has called unlock(), releasing a mutex, it is possible for another thread B to lock the same mutex, observe thatit is no longer in use, unlock it, and destroy it, before thread Aappears to have returned from its unlock call. Implementations arerequired to handle such scenarios correctly, as long as thread Adoesn't access the mutex after the unlock call returns. These casestypically occur when a reference-counted object contains a mutex thatis used to protect the reference count. — end note ]

3 The class mutex meets all of the mutex requirements ([thread.mutex.requirements]). It is a standard-layout class([class.prop]).

4 [Note: A program can deadlock if the thread that owns a mutex object calls lock() on that object. If the implementation can detect thedeadlock, a resource_­deadlock_­would_­occur error condition might beobserved. — end note ]

5 The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutexobject.


它只说“可以死锁”和“可能会被观察到”,否则它没有定义当你调用 lock 时会发生什么。在同一个线程中。
PS 在这种情况下要求抛出异常会使调用 lock更贵,没有任何实际好处。调用 lock在同一个线程中两次是你不应该做的事情。实际上你不应该调用 std::mutex::lock完全直接,因为手动释放锁不是异常安全的:
// shared block - bad
{
mut.lock();
// ... code ...
mut.unlock();
}
如果 ...code..然后抛出异常 mut永远不会解锁。解决这个问题的方法是 RAII,幸运的是标准库为锁提供了许多 RAII 助手,例如 std::lock_guard :
// shared block - good
{
std::lock_guard<std::mutex> lock(mut);
// ... code ...
}
TL;DR 不要这样做。
如果您的代码依赖于该异常,那么您将遇到比没有获得该异常更严重的问题。

关于c++ - 为什么互斥锁可以在 C++ 中锁定两次而不解锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63038287/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com