有谁可以指出我做错了什么? 我希望foo和bar可以交替打印 有时它会在第一次迭代中挂起,并且在某些情况下会在停止之前持续一段时间。
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
void foo()
{
while(true)
{
std::unique_lock<std::mutex> ul(m);
cv.wait(ul);
std::cout<<"bar"<<std::endl;
ul.unlock();
cv.notify_one();
}
}
int main()
{
std::thread t(foo);
while(true)
{
std::cout<<"foo"<<std::endl;
cv.notify_one();
std::unique_lock<std::mutex> ul(m);
cv.wait(ul);
}
}
答案 0 :(得分:1)
条件变量仅表示变化,它们本身并不是非常有用。你需要将它与一个州结合起来。
添加另一个变量,指示轮到谁了。
std::mutex m;
std::condition_variable cv;
int turn = 0;
void foo()
{
while(true)
{
std::unique_lock<std::mutex> ul(m);
if( turn == 1 ) {
// my turn
std::cout << "bar" << std::endl;
// tell them it's their turn
turn = 0;
cv.notify_one();
} else {
// not our turn, wait for a change.
cv.wait(ul);
}
}
}
int main()
{
std::thread t(foo);
while(true)
{
std::unique_lock<std::mutex> ul(m);
if( turn == 0 ) {
// my turn
std::cout << "foo" << std::endl;
// tell them it's their turn
turn = 1;
cv.notify_one();
} else {
// not our turn, wait for a change.
cv.wait(ul);
}
}
}
互斥锁用于安全访问turn
变量,无论何时更改,都会通知条件变量,以便其他线程可以唤醒并检查新值。
<小时/> 编辑:假设你理解上述内容,解决你的难题:
void foo()
{
std::unique_lock<std::mutex> ul(m);
while(true)
{
std::cout << "bar" << std::endl;
cv.notify_one();
cv.wait(ul);
}
}
int main()
{
std::unique_lock<std::mutex> ul(m);
std::thread t(foo);
while(true)
{
std::cout << "foo" << std::endl;
cv.notify_one();
cv.wait(ul);
}
}
换句话说,在启动子线程之前,您只需要从循环外部锁定互斥锁,这样对于先行的逻辑它就清楚了。然后你执行操作,发出信号,然后等待另一个线程发回信号。
逻辑流程:
Main Thread Sub Thread
------------------------------------------
Lock Mutex
Create Subthread
Try to lock mutex
but it is busy.
Print "foo" ...waiting for mutex...
Notify cvar ignores notification,
(still waiting for mutex)
Wait on cvar Obtains lock
(when waiting on a cvar, the lock is released.)
...waiting... Prints "bar"
Notified, but the Notify cvar
mutex is still locked
so we are waiting.
Obtains lock again Wait on cvar
Print "foo" ...waiting...
(etc...)
答案 1 :(得分:0)
好。 main
调用notify
,然后foo
调用notify
,然后main
锁定互斥锁并等待,然后foo
阻塞互斥锁。死锁。