C++ Double shared_lock 在 Windows 上冻结程序

c++ double shared_lock freezes the program on windows

提问人:user20011090 提问时间:9/24/2022 更新时间:9/24/2022 访问量:211

问:

当我学习 C++17 时,我发现了一个奇怪的问题。如果我在一个线程中调用两次,然后在另一个线程中调用,那么我的程序将冻结。喜欢这个:shared_mutexshared_lockunique_lock

std::mutex mutex;
std::shared_mutex s_mutex;

int i = 0;

void func() {
    auto lock = std::shared_lock(s_mutex);
    auto lock1 = std::shared_lock(s_mutex);
    ++i;
}

void func2() {
    auto lock = std::unique_lock(s_mutex);
    ++i;
}

int main() {
    auto t1 = std::thread([](){
        auto i = 10000;
        while(i--) {
            func();
        }
    });
    auto t2 = std::thread([](){
        auto i = 10000;
        while(i--) {
            func2();
        }
    });
    t2.join();
    t1.join();
    std::cout << i << std::endl;
    return 0;
}

这个问题似乎只出现在 Windows 上,我在 Arch linux 上尝试过,效果很好。

我正在使用 .g++.exe (Rev2, Built by MSYS2 project) 12.1.0

我尝试在每次锁定后添加,例如:cout

void func() {
    auto lock = std::shared_lock(s_mutex);
    std::cout << "t1 lock1\n";
    auto lock1 = std::shared_lock(s_mutex);
    std::cout << "t1 lock2\n";
    ++i;
}

然后我发现它总是在之后冻结,所以我尝试单步执行 lock1 的构造函数,我发现它在此函数之后冻结:t1 lock1\n

static inline int
__gthread_active_p (void)
{
  return 1;
}

但我不知道为什么。提前致谢。

C++ 死锁 ReadWriteLock

评论


答:

5赞 user17732522 9/24/2022 #1

尝试在已对互斥锁保持锁定的线程中再次锁定互斥锁具有未定义的行为。

这适用于除互斥锁类型之外的所有互斥锁类型。recursive*

评论

0赞 François Andrieux 9/24/2022
具体来说,“如果lock_shared被已经拥有互斥锁的线程在任何模式(独占或共享)中调用,则行为是未定义的 en.cppreference.com/w/cpp/thread/shared_mutex/lock_shared
0赞 Revolver_Ocelot 9/25/2022
通常,为了防止活锁,一旦线程尝试获取独占锁,所有新的共享锁尝试都会放在它后面的队列中。如果在另一个线程中的两次共享锁尝试之间发生获取独占锁的尝试,则一切都会死锁:第二个线程等待第一个线程释放第一个共享锁,而它停留在尝试获取第二个共享锁时,只有在第二个线程释放独占所有权后才会获得。