考虑以下场景:
线程1
mutexLk1_
gcondVar_.wait(mutexLk1);
Run Code Online (Sandbox Code Playgroud)
线程2
mutexLk2_
gcondVar_.wait(mutexLk2);
Run Code Online (Sandbox Code Playgroud)
线程3
condVar_
gcondVar_.notify_all();
Run Code Online (Sandbox Code Playgroud)
我观察到,并notify_all()没有唤醒两个线程,而是只唤醒两个线程中的一个。如果我要替换mutexLk2为mutexLk1. 我得到了一个功能代码。
要重现该问题,请考虑以下来自cppref的修改示例
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
std::condition_variable cv;
std::mutex cv_m1;
std::mutex cv_m; // This mutex is used for three purposes:
// 1) to synchronize accesses to i
// 2) to synchronize accesses to std::cerr
// 3) for the condition variable cv
int i = 0;
void waits1()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk, []{return i == 1;});
std::cerr << "...finished waiting. waits1 i == 1\n";
}
void waits()
{
std::unique_lock<std::mutex> lk(cv_m1);
std::cerr << "Waiting... \n";
cv.wait(lk, []{return i == 1;});
std::cerr << "...finished waiting. i == 1\n";
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
std::cerr << "Notifying again...\n";
}
cv.notify_all();
}
int main()
{
std::thread t1(waits), t2(waits1), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
Run Code Online (Sandbox Code Playgroud)
编译命令
g++ --std=c++17 t.cpp -lpthread
这里有趣的是,上面的代码在带有 g++ 9.3 版本的 centos 7.9 系统上(与该系统上的 g++ 10 的行为相同)但在 ubuntu 18.04 系统(带有 g++)上卡在任一等待上(有时 waits1 运行有时等待) 9.4)这可以正常工作,没有任何问题
知道要遵循的预期行为或理想实践是什么吗?因为在我的使用案例中,我需要两个不同的互斥体来保护不同的数据结构,但触发器来自相同的条件变量。
谢谢
看来你违反了标准:
\n\n\n33.5.3 类condition_variable [thread.condition.condvar]
\n无效等待(unique_lock&lock);
\n要求:lock.owns_lock() 为 true 并且 lock.mutex() 被调用线程锁定,并且
\n(9.1) \xe2\x80\x94 没有其他线程正在等待此 condition_variable 对象\nor
\n(9.2) \xe2\x80\x94 lock.mutex() 为所有并发等待(通过 wait、wait_for 或 wait_until)线程提供的每个锁\参数返回相同的值。
\n
清楚两个线程正在等待,并且 lock.mutex() 不返回相同的值。
\n| 归档时间: |
|
| 查看次数: |
1149 次 |
| 最近记录: |