#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
为什么会发生这种情况?我的目标是让这个程序持续运行,直到我手动停止它。
您不能在同一线程上多次调用
lock_shared
。 mutex.lock_shared(); mutex.lock_shared();
是未定义的行为。您需要类似于 std::recursive_mutex
的东西,但需要 shared_mutex
才能做到这一点。
这个UB可能是导致死锁的原因