*/
//单例设计模式:
/*
整个程序中某个或者某些特殊的类,他们只能创建一个对象(一般为数据共享)。
单例类,只能生成一个对向。
设计模式共享数据问题分析,解决
如果数据是只读的,多个线程同时调用没有问题,所以单例一般适合在只读数据上使用。
一般单例用来储存全局唯一变量。例如银行的货币的汇率。
建议:在创建其他线程之前,在主线程中就把单例的成员初始化和数据装载。
*/
//在子线程中创建单例
/*
面临问题:需要在我们自己创建的线程中创建MYCAS这个单例类对象,这样的线程最少两个、
所以GetInstance()这种成员函数需要互斥。
*/
//stable is the most important thing.
//std::call_once()
/*
c++11,该函数的第二个参数是一个函数名,eg:a()
call_once功能时能够保证a()只被调用一次,具备互斥量这样的能力,而且效率比互斥量更高
但是需要和std::onec_flag这个标记结合使用。onec_flag是一个结构。
call_once()就是通过这个标记来决定对应的函数a()是否执行,调用call_once()成功后,call_once
就把这个标记设置为一种一调用状态
once_flag设置为一调用状态,那么对应的函数a()就不会再被执行了。
*/
#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
mutex resource_mutex;//因为是静态函数引用,所以不能添加在类的private里。
std::once_flag g_flag;//标志符
class A {
mutex my_mutex1;
list<int>msgRecvQueue;
std::condition_variable my_cond;
public:
void inMsgRecvQueue()
{
for (int i = 0; i < 10000; i++)
{
//my_condi 中的lambda返回false,释放mutex1,这里就会得到mutex1
std::unique_lock<std::mutex>inLock(my_mutex1);
cout << "Insert a num in inMSG: " << i << endl;
msgRecvQueue.push_back(i);
my_cond.notify_one();//尝试把wait()的线程唤醒,wait()会再次尝试获取mutex的权限。一次只能唤醒一个线程。
//不是1:1唤醒,两个可能同时争夺锁,in线程可能连续拿到两次锁,运行两次。
my_cond.notify_all();//wake all the threads up.
//std::chrono::milliseconds t (2000);
//std::sl
}
return;
}
void outMsgRecvQueue()
{
int command = 0;
while (true)
{
std::unique_lock<std::mutex>outlock(my_mutex1);
//wait()用来等待一个东西
/*
如果第二个参数lambda表达式返回值是false,那么wait()将解锁互斥量,并堵塞到本行。
堵塞到其他某个线程调用notify_one()成员函数为止。
*/
//如果wait中没有第二个参数
/*
等于返回false,解锁互斥量mutex1,堵塞线程,直到范湖notify_one一样
*/
//[this...return false;});是lambda表达式相当于一个返回结果的函数=一个变量参数
my_cond.wait(outlock, [this] {//一个lambda表达式就是一个可调用对象(函数)
if (!msgRecvQueue.empty())
return true;
return false;});
command = msgRecvQueue.front();
msgRecvQueue.pop_front();
cout << "The number in the msg: " << command << ".ThreadID is "<<this_thread::get_id()<<endl;
outlock.unlock();//We can unlock the unique lock,because of the flexiable of unique_lock.
}
}
};
int main()
{
A myobj;
std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用,才能保证线程里用的是同一个对象
std::thread myOutMsgObj2(&A::outMsgRecvQueue, &myobj);//notify_all();
std::thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
myInMsgObj.join();
myOutMsgObj.join();
return 0;
}
c++多线程唤醒notify_all与notify_one
最新推荐文章于 2024-03-09 21:05:38 发布