admin管理员组

文章数量:1599529

condition_variable也是在多线程编程中经常用到的一个类。使用的时候需要包含头文件<condition_variable>

condition_variable

condition_variable对象能使调用线程阻塞,直到被notify去唤醒。这个性质经常在多线程编程中使用,因为在多线程编程中经常遇到一个线程需要等待某个条件然后继续执行的情况。

一般使用unique_lock(一般结合mutex使用)对象,通过调用condition_variable的wait函数锁定一个线程,直到另外一个线程调用同一个condition_variable对象的notify函数,该线程会再次唤醒。就是说condition_variable对象通常用unique_lock<mutex>去等待。如果想要用其他类似unique_lock类型的对象,可以参考condition_variable_any类。

构造函数
构造函数
default(1)condition_variable();
copy [deleted](2) condition_variable(const condition_variable&) = delete;
也就是说condition_variable是禁止复制的。
wait函数
wait
unconditional(1)void wait(unique_lock< mutex > &lck)
predicate(2)template < class Predicate>
void wait(unique_lock< mutex> &lck, Predicate pred);
对于函数(1),调用该函数后,当前正在执行的线程将会阻塞,直到condition_variable对象被其他线程notify后将继续执行。

当线程被阻塞后的,该函数会自动调用lck.unlock(),释放相关mutex,以至于其他lock相同mutex的线程能够继续执行。当被通知后,会再次自动调用lck.lock()。

对于函数(2),大致情况和(1),是一样的,只是当条件pred,是false时,调用线程才会阻塞。如果是true则不阻塞,而是继续执行。

notify_one函数

唤醒正在通过相同的condition_variable对象等待而阻塞的线程。如果没有线程等待,则什么都不做。如果有多个线程等待,则选择其中一个,具体选择哪一个则不确定。

示例代码如下:

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>

using namespace std;

mutex mtx;
mutex mtx1;
condition_variable cv1;
condition_variable cv2;
int g_count = 0;

void func(int n)
{
	for (int i = 0; i < n; i++)
	{
		unique_lock<std::mutex> lock(mtx);
		cv1.wait(lock);
		cout << g_count << endl;
		cv2.notify_one();
	}
}

int main()
{
	int n = 5;
	thread t(func, n);
	this_thread::sleep_for(chrono::milliseconds(1000));
	for (int i = 0; i < n; i++)
	{
		{	
			unique_lock<mutex> lock(mtx);
			g_count++;
			cv1.notify_one();
		}
		unique_lock<mutex> lock(mtx1);
		cv2.wait(lock);
	}
	t.join();
	
	getchar();
	return 0;
}

输出结果如下:

其他函数

除了以上函数之外还有几个成员函数能用到,比如:notify_all,wait_for,wait_until。

notify_all
唤醒所有使用相同condition_variable变量等待而阻塞的线程,如果没有等待的线程,则什么都不做。

wait_for
该函式和wait很相似,只不过加上了一个时间限制。就是等到时间到了或者被notify了后唤醒线程。该函数和wait一样有无先决条件和有先觉条件两种如下:

wait_for
unconditional(1)template < class Rep, class Period>
cv_status wait_for (unique_lock< mutex>& lck, const chrono::duration< Rep,Period>& rel_time);
predicate(2)template < class Rep, class Period, class Predicate>
bool wait_for (unique_lock< mutex>& lck, const chrono::duration< Rep,Period>& rel_time, Predicate pred);
其中(2)是如果pred为false才阻塞,为true则不阻塞。

wait_until
该函数和wait_for非常相似,只是wait_for是等待一段时间,而wait_until是等待到一个时间点。其他的都一样,不多赘述。

wait_until
unconditional(1)template < class Clock, class Duration>
cv_status wait_until (unique_lock< mutex>& lck, const chrono::time_point< Clock,Duration>& abs_time);
predicate(2)template < class Clock, class Duration, class Predicate>
bool wait_until (unique_lock< mutex>& lck, const chrono::time_point< Clock,Duration>& abs_time, Predicate pred);

本文标签: conditionvariable