C++ 11 线程 condition_variable

condition_variable

(C++11)

provides a condition variable associated with a std::unique_lock

condition_variable
  
(C ++ 11)
 
提供与std :: unique_lock关联的条件变量 

Example

condition_variable is used in combination with a std::mutex to facilitate inter-thread communication.

 例1
condition_variable与std :: mutex结合使用以促进线程间通信。

当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

std::condition_variable 对象通常使用 std::unique_lock<std::mutex> 来等待,如果需要使用另外的 lockable 类型,可以使用 std::condition_variable_any 类,本文后面会讲到 std::condition_variable_any 的用法。

// threadTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;

void worker_thread()
{
	//std::this_thread::sleep_for(std::chrono::seconds(1));
	// wait until main() sends data
	std::unique_lock<std::mutex> lk(m);
	std::cout << "thread lk.lock\n";
	// here m will be unlocked,and will wait other thread notify ,if recive other thread notify,this thread will go on.
	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 befor nodifying, 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<std::mutex> lk(m);
		std::cout << "main lk.lock\n";
		ready = true;
		std::cout << "main() signals data ready for processing\n";
	}
	cv.notify_one();

	// wait for the worker

	{
		std::unique_lock<std::mutex> lk(m);
		cv.wait(lk, [] {return processed; });
	}

	std::cout << "Back in main(),data = " << data << '\n';
	worker.join();
    return 0;
}

运行结果:

 cv.wait()会将锁unlock,然后自己等着,如果其他线程发送了通知,则会继续执行,并将锁lock。

例2

// threadTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>
class condvarQueue
{
	std::queue<int> produced_nums;
	std::mutex m;
	std::condition_variable cond_var;
	bool done = false;
	bool notified = false;
public:
	void push(int i)
	{
		std::unique_lock<std::mutex> lock(m);
		produced_nums.push(i);
		notified = true;
		cond_var.notify_one();
	}

	template<typename Consumer>
	void consume(Consumer consumer)
	{
		std::unique_lock<std::mutex> lock(m);
		while (!done) {
			while (!notified) {
				cond_var.wait(lock);
			}
			while (!produced_nums.empty()) {
				consumer(produced_nums.front());
				produced_nums.pop();
			}
			notified = false;
		}
	}

	void close()
	{
		done = true;
		notified = true;
		cond_var.notify_one();
	}

 };
int main()
{
	condvarQueue queue;

	std::thread producer([&]() {
		for (int i = 0; i < 5; i++) {
			std::this_thread::sleep_for(std::chrono::seconds(1));
			std::cout << "producing" << i << '\n';
			queue.push(i);
		}
		queue.close();
	});

	std::thread consumer([&]() {
		queue.consume([](int input) {
			std::cout << "consuming " << input << '\n';
		});
	});
	producer.join();
	consumer.join();
    return 0;
}

运行结果:

producing0
consuming 0
producing1
consuming 1
producing2
consuming 2
producing3
consuming 3
producing4
consuming 4
请按任意键继续. . .

例3 .notify_all

// threadTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>

std::condition_variable cv;
std::mutex cv_m;// This mutex is used for three purposes
				// 1) to synchronize accesses to i
				// 2) to synchronize accesses to std::cerr
				// 3) for the condition variable cv
int i = 0;

void waits()
{
	std::unique_lock<std::mutex> lk(cv_m);
	std::cerr << "Waiting... \n";
	cv.wait(lk, [] {return i == 1; });// only when i ==1, wait will return
	std::cerr << "...finished waiting.i == 1\n";
}

void signals()
{
	std::this_thread::sleep_for(std::chrono::seconds(1));
	{
		std::lock_guard<std::mutex> lk(cv_m);
		std::cerr << "Notifying...\n";
	}
	cv.notify_all();
	
	std::this_thread::sleep_for(std::chrono::seconds(1));
	{
		std::lock_guard<std::mutex> lk(cv_m);
		i = 1;
		std::cerr << "Notifying again...\n";
	}
	cv.notify_all();
}
int main()
{
	std::thread t1(waits), t2(waits), t3(waits), t4(signals);
	t1.join();
	t2.join();
	t3.join();
	t4.join();
    return 0;
}



//output
/*
Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting.i == 1
...finished waiting.i == 1
...finished waiting.i == 1
请按任意键继续. . .
*/
发布了257 篇原创文章 · 获赞 22 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_24127015/article/details/104834610