从 std::scoped_lock 抛出的异常

Posted

技术标签:

【中文标题】从 std::scoped_lock 抛出的异常【英文标题】:exception thrown from std::scoped_lock 【发布时间】:2019-05-14 10:37:15 【问题描述】:

我正在尝试从另一个线程锁定互斥体,以清除向量,使用 scoped_lock,期望代码将等到另一个线程释放它。

但是发生的情况是,试图获取锁的函数抛出异常,说明资源正忙。

//Called from thread 1
Foo::DoStuff()

    std::scoped_lock<std::mutex>(m_lock);
    for (auto thing: stuff) //should be non trivial in size
    
        thing->bar();
    


//called from thread 0
Foo::ClearStuff()

    try
    
        std::scoped_lock<std::mutex>(m_lock); //throws 
        stuff.clear();
    
    catch (const std::exception& e)
    
        std::cout << e.what() << std::endl;
        // device or resource busy: device or resource busy
    

我的线程知识基于 SDL2 线程库,所以我不确定自己做错了什么。我使用了错误的线程构造吗?如果是这样,我应该使用什么来确保调用等到互斥锁被释放?

【问题讨论】:

std::scoped_lock&lt;std::mutex&gt;(m_lock); 这会创建临时锁 - 未命名的实例,该实例在行尾被销毁。您的代码中没有同步。 barclear 可能同时发生,导致 UB。 你需要通过给你的作用域锁一个名字来创建一个变量。否则它的作用域只持续到分号。 【参考方案1】:

您需要存储作用域锁。实际上,锁被获取到一个临时变量中,该变量立即被销毁,释放锁。

std::scoped_lock<std::mutex> lock(m_lock);

旁注:我会称它为m_stuff_mtx 而不是m_lock,因为它控制对stuff 的访问,是一个互斥体,还有其他东西在起作用,称为锁。

【讨论】:

以上是关于从 std::scoped_lock 抛出的异常的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获从 iframe 内部抛出的异常?

为啥我看不到从 java 守护线程抛出的异常 [重复]

如果在“等待”之后抛出,则从任务中抛出的异常被吞下

从 lambda 表达式中抛出的已检查异常

XmlDocument.Save 从 GC 线程抛出的未处理异常

PHP 检查抛出的异常类型