给公司做一个网站流程,中药材初加工平台,dedecms与wordpress,wordpress可以做淘宝客今天无意中看到一篇帖子#xff0c;关于条件变量的#xff0c;不过仔细看看发现它并达不到原本的目的。
程序如下#xff0c;读者可以先想想他的本意#xff0c;以及有没有问题#xff1a;
#include iostream
#include thread
#include condition_v…今天无意中看到一篇帖子关于条件变量的不过仔细看看发现它并达不到原本的目的。
程序如下读者可以先想想他的本意以及有没有问题
#include iostream
#include thread
#include condition_variable
#include mutex
#include unistd.h
using namespace std;
//全局条件变量
condition_variable cond;
mutex _mutex;
int count 0;void fun1(){while(1){count;unique_lockmutexlock(_mutex);if(count%5 0){cond.notify_one();}else{coutthis is fun1,countcountendl;}lock.unlock();sleep(1);}
}void fun2()
{while(1){unique_lockmutexlock(_mutex);cond.wait(lock);coutthis is fun2,countcountendl;lock.unlock();sleep(2);}
}int main()
{thread t1(fun1);thread t2(fun2);t1.join();t2.join();return 0;
}
OK本意显然是
从1开始打印整数线程t1, 打印非5的倍数线程t2, 打印5的倍数
编译执行运行的还不错符合预期但这都是sleep的功劳。把fun1中的sleep去掉fun2中的sleep放到cond.wait(lock)后它BUG的面目就暴露出来了
void fun1(){while(1){count;unique_lockmutexlock(_mutex);if(count%5 0){cond.notify_one();}else{coutthis is fun1,countcountendl;}lock.unlock();}
}void fun2()
{while(1){unique_lockmutexlock(_mutex);cond.wait(lock);sleep(2);coutthis is fun2,countcountendl;lock.unlock();}
}[mzhailock]$ ./a.out
this is fun1,count1
this is fun1,count2
this is fun1,count3
this is fun1,count4
this is fun2,count6
this is fun1,count6
this is fun1,count7
this is fun1,count8
this is fun1,count9
this is fun1,count11
this is fun1,count12
this is fun1,count13
this is fun1,count14
this is fun1,count16
this is fun1,count17
this is fun1,count18
this is fun1,count19
this is fun1,count21多线程结果不能因随机加了几个sleep就不同加sleep仅仅是模拟线程调度不大一样了。 再回过头来看看代码哪些地方有问题 cond.notify_one(); count是5的倍数时t1会通过notify_one通知t2做事但并不会阻止t1继续执行。想想一下如果t1执行的很快而t2一直没得到调度则t1会打印1234678911...cond.wait(lock); 可能会假唤醒此时t1并没有通知它。 那“this is fun2,count6” 是怎么回事哪不应该是5吗一种可能性是可以通过GDB调试来模拟 说了那么多怎么改哪 这是一个典型的你等我我等你的例子对于这个例子都是一方干完事情另一方才能继续完全串休化的任务直接写到一个线程里即可。如果说我为了练习线程同步技巧非要整两个线程那也行condition_variable官方文档上就有一个例子实现了main线程等待worker_thread完成任务
#include condition_variable
#include iostream
#include mutex
#include string
#include threadstd::mutex m;
std::condition_variable cv;
std::string data;
bool ready false;
bool processed false;void worker_thread()
{// Wait until main() sends datastd::unique_lock lk(m);cv.wait(lk, []{ return ready; });// after the wait, we own the lock.std::cout Worker thread is processing data\n;data after processing;// Send data back to main()processed true;std::cout Worker thread signals data processing completed\n;// Manual unlocking is done before notifying, to avoid waking up// the waiting thread only to block again (see notify_one for details)lk.unlock();cv.notify_one();
}int main()
{std::thread worker(worker_thread);data Example data;// send data to the worker thread{std::lock_guard lk(m);ready true;std::cout main() signals data ready for processing\n;}cv.notify_one();// wait for the worker{std::unique_lock lk(m);cv.wait(lk, []{ return processed; });}std::cout Back in main(), data data \n;worker.join();
}
我们依样画葫芦
#include iostream
#include thread
#include condition_variable
#include mutex
#include unistd.h
using namespace std;
//全局条件变量
condition_variable cond;
mutex _mutex;
bool ready false;
bool processed false;int count 0;void fun1(){while(1){count;unique_lockmutex lock1(_mutex);if(count%5 0){ready true;processed false;lock1.unlock();cond.notify_one();lock1.lock();cond.wait(lock1, []{ return processed; });}else{coutthis is fun1,countcountendl;}lock1.unlock();}
}void fun2()
{while(1){unique_lockmutex lock1(_mutex);cond.wait(lock1, []{ return ready; });coutthis is fun2,countcountendl;processed true;ready false;lock1.unlock();cond.notify_one();}
}int main()
{thread t1(fun1);thread t2(fun2);t1.join();t2.join();return 0;
}结果符合预期感兴趣的读者可以到处插入sleep测试一下。