在锁定时释放持有互斥锁的对象

时间:2016-10-13 19:57:01

标签: c++ multithreading mutex deadlock

我遇到了存储在实例中的互斥锁的问题。举个例子,我写了这个:

#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include "Sleep.h"

struct Test
{
    std::shared_mutex mutex;
};

Test* test = new Test();

void t1()
{
    std::unique_lock<std::shared_mutex> lock(test->mutex);
    SLEEP(200);
    delete test;
    std::cout << "thread 1" << std::endl;
}

void t2()
{
    SLEEP(100);
    std::cout << "hold" << std::endl;
    std::shared_lock<std::shared_mutex> lock(test->mutex);
    std::cout << "thread 2" << std::endl;
}

int main()
{
    std::thread trd1 = std::thread(&t1);
    std::thread trd2 = std::thread(&t2);
    trd1.join();
    trd2.join();

    std::cin.get();
    return 0;
}

我想要的是,只要删除test并使用互斥引用(?), shared_lock 就会解锁。目标是删除一个由多个线程使用的对象,线程安全。至于在 shared_lock 之后发生的事情并不重要(我知道我不能再使用test了。)

输出结果为:

hold
thread 1
(here should be 'thread 2')

但不幸的是,t2似乎陷入僵局。

问题

  1. 有没有办法让shared_lockunique_lock超出范围后继续? (重要的是使用实例的互斥锁)
  2. 在测试时,我也尝试用shared_mutex替换shared_timed_mutex。令我惊讶的是,它会在t1()结束时导致崩溃。那是为什么?

1 个答案:

答案 0 :(得分:3)

您正在通过在锁定仍使用互斥锁时删除unique_lock所持有的互斥锁来调用未定义的行为。

根据语言标准,unique_lock类的描述(§30.4.2.2):

  

如果[lock持有的互斥锁]在unique_lock对象的整个剩余生命周期内不存在,则程序的行为是未定义的。

在销毁互斥锁​​(或包含互斥锁的类)之前,您必须销毁或释放锁。