std::shared_mutex 在没有写锁的情况下无法获取读锁

问题描述 投票:0回答:1
#include "shared_mutex"
#include "thread"
#include "iostream"
#include "string"

using namespace std::chrono_literals;

struct debug_mutex : public std::shared_mutex {
    void lock() noexcept {
        std::string m = "Try To lock, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                        std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m << std::endl;
        std::shared_mutex::lock();
        unique_lock_c.fetch_add(1);
        std::string m1 = "lock, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                         std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m1 << std::endl;
    }

    void unlock() noexcept {
        std::string m = "Try To unlock, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                        std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m << std::endl;
        std::shared_mutex::unlock();
        unique_lock_c.fetch_add(-1);
        std::string m1 = "unlock, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                         std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m1 << std::endl;
    }

    void lock_shared() noexcept {
        std::string m = "Try To lock_shared, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                        std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m << std::endl;
        std::shared_mutex::lock_shared();
        shared_lock_c.fetch_add(1);
        std::string m1 = "lock_shared, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                         std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m1 << std::endl;
    }

    void unlock_shared() noexcept {
        std::string m = "Try To unlock_shared, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                        std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m << std::endl;
        std::shared_mutex::unlock_shared();
        shared_lock_c.fetch_add(-1);
        std::string m1 = "unlock_shared, u_count: " + std::to_string(unique_lock_c.load()) + ", s_count" +
                         std::to_string(shared_lock_c.load()) + "\n";
        std::cout << m1 << std::endl;
    }

    std::atomic_uint64_t shared_lock_c{0};
    std::atomic_uint64_t unique_lock_c{0};
} mutex;

int main(int argc, char **argv) {
    std::thread t{[]() {
        std::this_thread::sleep_for(10ns);
        while (true) {
            mutex.lock_shared();
            mutex.lock_shared();
            mutex.lock_shared();
            mutex.lock_shared();
            mutex.lock_shared();
            mutex.lock_shared();
            std::this_thread::sleep_for(5ns);
            mutex.unlock_shared();
            mutex.unlock_shared();
            mutex.unlock_shared();
            mutex.unlock_shared();
            mutex.unlock_shared();
            mutex.unlock_shared();
            std::cout << "read lock once" << std::endl;
        }
    }};
    std::thread t1{[]() {
        std::this_thread::sleep_for(5ms);
        while (true) {
            mutex.lock();
            std::this_thread::sleep_for(5ms);
            mutex.unlock();
            std::cout << "write lock once" << std::endl;
        }
    }};
    t.join();
    t1.join();
}

这个程序是一个带有日志记录的简单示例。 (请忽略析构函数之类的内容,仅用于记录目的。)

它应该连续运行,读锁和写锁互不干扰,但在不应该的时候它会卡住。

日志显示,卡住的时候,实际上并没有获取到写锁,但是读锁也获取不到。

Try To lock_shared, u_count: 0, s_count4
lock_shared, u_count: 0, s_count5
Try To lock, u_count: 0, s_count5
Try To lock_shared, u_count: 0, s_count5

为什么会发生这种情况?我的目标是让这个程序持续运行,直到我手动停止它。

c++ multithreading mutex deadlock
1个回答
0
投票

您不能在同一线程上多次调用

lock_shared
mutex.lock_shared(); mutex.lock_shared();
是未定义的行为。您需要类似于
std::recursive_mutex
的东西,但需要
shared_mutex
才能做到这一点。

这个UB可能是导致死锁的原因

© www.soinside.com 2019 - 2024. All rights reserved.