Location>code7788 >text

C++11 Simple Use of the Thread Synchronization Interfaces std::condition_variable and std::future

Popularity:220 ℃/2024-09-19 11:23:40

std::condition_variable

The condition variable std::condition_variable has wait and notify interfaces for inter-thread synchronization. As shown in the following figure, Thread 2 blocks on the wait interface, and Thread 1 notifies Thread 2 to continue execution via the notify interface.

con_variable_result

See the sample code for details:

#include<iostream>
#include<mutex>
#include<thread>
#include<queue>
std::mutex mt;
std::queue<int> data;
std::condition_variable cv;
auto start=std::chrono::high_resolution_clock::now();

void logCurrentTime()
{
	auto end = std::chrono::high_resolution_clock::now();
	auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
	std::cout << elapsed << ":";
}
void prepare_data()
{	
	logCurrentTime();
	std::cout << "this is " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;
	for (int i = 0; i < 10; i++)
	{
		(i);
		logCurrentTime();
		std::cout << "data OK:" << i << std::endl;
	}
	//start to notify consume_data thread data is OK!
	cv.notify_one();
}


void consume_data()
{
	logCurrentTime();
	std::cout << "this is: " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;
	std::unique_lock<std::mutex> lk(mt);
	//wait first for notification
	(lk);  //it must accept a unique_lock parameter to wait

	while (!())
	{
		logCurrentTime();
		std::cout << "data consumed: " << () << std::endl;
		();
	}
}


int main()
{
	std::thread t2(consume_data);
	//wait for a while to wait first then prepare data,otherwise stuck on wait
	std::this_thread::sleep_for(std::chrono::milliseconds(10));
	std::thread t1(prepare_data);
	();
	();
	return 0;
}

output result

con_variable_result

analyze

In the main thread, two threads are started to execute consume_data and prepare_data, where consume_data should be executed first to ensure that it waits before notifying, otherwise it will be deadlocked if it notifies first and then waits. First the consume_data thread is started after the first notification from thewait The queue is blocked and waits. The latter prepare_data thread writes 0-10 to the queue in turn, and after that writes 0-10 to the queue via thenotify_one Notify the consume_data thread to unblock and read 0-10 in turn.

std::future

std::future works with std::async to execute the code asynchronously, and then blocks the current thread waiting for the result via the wait or get interface. As shown in the following figure, the get or wait interface of the future interface in Thread 2 will block the current thread, and the new thread Thread1 opened by std::async asynchronously will notify Thread 1 to get the result after it finishes executing by storing the result in std::future and then continue executing.

con_variable_result

See the code below for details:

#include <iostream>
#include <future>
#include<thread>

int test()
{
	std::cout << "this is " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;;
	std::this_thread::sleep_for(std::chrono::microseconds(1000));
	return 10;
}
int main()
{
	std::cout << "this is " <<__FUNCTION__<<" thread:" << std::this_thread::get_id() << std::endl;;
	//this will lanuch on another thread
	std::future<int> result = std::async(test);

	std::cout << "After lanuch a thread: "<< std::this_thread::get_id() << std::endl;

	//block the thread and wait for the result
	std::cout << "result is: " <<()<< std::endl;

	std::cout << "After get result "<< std::endl;

	return 0;
}

output result

运行结果

analyze

The main program calls std::async to call the test function asynchronously, you can see that the thread ID 27428 of the main function is not the same as the thread ID 9704 of the test function, which means that std::async starts a new thread. In the test thread, sleep 1000ms first, so you can see that "After lanuch a thread:" is output first, indicating that the main thread executes asynchronously and is not affected by the sub-threads. And "After get result" is output last, which means get() method will block the main thread until the result is obtained.