C++并发与多线程---学习笔记(5)condition_variable、wait、notify_one、notify_all

C++11并发与多线程

  • 一、条件变量condition_variable、wait()、notify_one()
    • 1)condition_variable
    • 2)wait()
    • 3)notify_one()
  • 二、notify_one()与notify_all()区别


一、条件变量condition_variable、wait()、notify_one()

1)condition_variable

  • std::condition_variable实际使用一个类,是一个和条件相关的一个类,说白了就是等待一个条件达成,这个类需要和互斥量来配合工作

2)wait()

  • 该函数是用来等待要处理的事情
#include
#include
#include
#include
#include
#include

using namespace std;

class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
		}
		return;
	}

	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);
			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
		}	
	}
private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

int main() {

	example ex;
	thread out(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread in(&example::messagein, &ex);
	out.join();
	in.join();

	cout << "主线程运行" << endl;
	system("pause");
	return 0;
}
  • wait()函数参数的讲解以及用法:

  • 1、如果第二个参数lambda表达式返回值是true,那么wait()直接返回,继续执行下面的代码

  • 2、如果第二个参数lambda表达式返回值是false,那么wait()将解锁互斥量,并阻塞到本行,那阻塞到什么时候呢?阻塞到其他某个线程调用notify_one()成员函数为止

  • 3、如果没有第二个参数,代码中mycond.wait(guard)那么就跟第二个参数lambda表达式返回false效果一样,wait()将解锁互斥量,并阻塞到本行,阻塞到其他某个线程调用notify_one()成员函数为止

  • 4、当其他线程用notify_one()将本wait(原来是阻塞/堵塞)的状态唤醒后,wait就开始恢复干活,恢复后wait干什么

    • a):wait()不断的尝试重新获取互斥量,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了锁(等于加了锁),那么wait就继续执行b)
    • b):
      • b.1)如果wait有第二个参数(lambda),就判断这个lambda表达式,如果lambda表达式为false,那么wait又对互斥量解锁,然后又休眠这里等待再次被notify_one()唤醒
      • b.2)如果lambda表达式为true,则wait返回,流程走下来(此时互斥量被锁着)
      • b.3)如果wait没有第二个参数,则wait返回,流程走下来

3)notify_one()

  • 该函数用来唤醒wait()
class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
			mycond.notify_one();//尝试把wait()的线程唤醒,执行完这行,那么messageout()里边的wait就会唤醒
		}
		return;
	}
	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);

			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
			//流程只要能走下来这里,互斥锁一定是锁住,同时num至少是有一条数据的
			command = num.front();
			num.pop_front();
			cout << "messageout()执行,取出一个元素:" << command <<",thread_id:"<<this_thread::get_id()<< endl;
			guard.unlock();//临时解锁,(unique_lock的灵活性,所以我们可以随时的unlock,以免锁住太长时间)
			//执行一些具体动作,需要100毫秒的处理时间
			//。。。。。。
		}
	}
private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

二、notify_one()与notify_all()区别

  • notify_one():通知一个线程的wait()

  • notify_all():通知所有线程的wait()

    当有多个线程使用wait()时,notify_one()一个一个这样唤醒会影响运行效率,因此notify_all()会比notify_one()好用

#include
#include
#include
#include
#include
#include

using namespace std;

class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
			mycond.notify_all();

		}
		return;
	}
	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);
			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
			//流程只要能走下来这里,互斥锁一定是锁住,同时num至少是有一条数据的
			command = num.front();
			num.pop_front();
			cout << "messageout()执行,取出一个元素:" << command <<",thread_id:"<<this_thread::get_id()<< endl;
			guard.unlock();//临时解锁,(unique_lock的灵活性,所以我们可以随时的unlock,以免锁住太长时间)

			//执行一些具体动作,需要100毫秒的处理时间
			//。。。。。。

		}
			
	}

private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

int main() {
	example ex;
	thread out(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread out1(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread in(&example::messagein, &ex);
	out.join();
	out1.join();
	in.join();

	cout << "主线程运行" << endl;
	system("pause");
	return 0;
}

你可能感兴趣的:(c++,多线程,c++11,多线程,并发编程,c++,lambda)