【C++多線程系列】【十】future與promise

當兩個線程間須要傳遞數據時,能夠使用promise與future來實現。ios

線程A經過promise.setvalue來設置數據,線程B經過promise的get_future獲取future後,從future中獲取數據。future寫用法與前面博文用法一致。promise

【一】設置數據與獲取數據spa

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;

void f(future<int> &fu)
{
	cout << fu.get() << endl;
}


int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	thread t1(f, std::ref(fu));
	
	pro.set_value(10);

	t1.join();
	cout << "main" << endl;
	system("pause");
}

結果以下:線程

【二】只get,不set設計

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;

void f(future<int> &fu)
{
	cout << fu.get() << endl;
}


int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	thread t1(f, std::ref(fu));
	
	//pro.set_value(10);

	t1.join();
	cout << "main" << endl;
	system("pause");
}

子線程會一直阻塞在fu.get上code

【三】set一次,get屢次get

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;

void f(future<int> &fu)
{
	cout << fu.get() << endl;
	cout << fu.get() << endl;
}


int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	thread t1(f, std::ref(fu));
	
	pro.set_value(10);

	t1.join();
	cout << "main" << endl;
	system("pause");
}

程序會運行失敗。當使用promise set_value時,future便處於ready狀態,能夠get到值,第二次get時,因爲future被get了一次,不能夠被get第二次,因此第二次get會失敗。future設計上,就是隻能get一次it

同時,promise只能被set一次,不能被set第二次。io

以下程序會崩潰class

int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	//thread t1(f, std::ref(fu));
	
	pro.set_value(10);
	pro.set_value(10);

	//t1.join();
	cout << "main" << endl;
	system("pause");
}

若是隻set,而沒有get,是沒有問題的

int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	//thread t1(f, std::ref(fu));
	
	pro.set_value(10);
	//pro.set_value(10);

	//t1.join();
	cout << "main" << endl;
	system("pause");
}

【四】一個線程set,兩個線程get

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;

void f(future<int> &fu)
{
	cout << "f"<<fu.get() << endl;
	//cout << fu.get() << endl;
}
void f2(future<int> &fu)
{
	cout << "f2"<<fu.get() << endl;
	//cout << fu.get() << endl;
}


int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	thread t1(f, std::ref(fu));
	thread t2(f, std::ref(fu));
	
	pro.set_value(10);
	//pro.set_value(10);

	t1.join();
	t2.join();
	cout << "main" << endl;
	system("pause");
}

該程序會崩潰。

 

【五】注意點。join的位置應該在set以前,不然子線程會因爲沒有數據而一直等待

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;

void f(future<int> &fu)
{
	cout << "f"<<fu.get() << endl;
}



int main(int argc, int * argv[])
{
	promise<int> pro;
	future<int> fu = pro.get_future();

	thread t1(f, std::ref(fu));

	t1.join();
     
    pro.set_value(10);  // set在join以後,子線程會一直等待,而主線程也一直在等待子線程運行結束後纔會set,因此造成死循環。

	cout << "main" << endl;
	system("pause");
}

 

 

總結:使用future與promise進行線程間數據共享,其實是一種一次性消費,僅支持一對一,並且是一次性消費,不能再使用第二次。

相關文章
相關標籤/搜索