(7)Feature,Promise和async()
其實,這節課程中一開始的引入future的環節不是太清晰,反正只要知道使用了future, 在程式碼中可以省略mutex 和條件變數的使用,並且也保證了主執行緒在得到x的值的過程,一定是在子執行緒結束後發生.而這個程式碼段是為了得到從執行緒中返回值.
#include <deque>
#include <functional>
#include <iostream>
#include <fstream>
#include <thread>
#include <string>
#include <mutex>
#include <future>
using namespace std;
int factorial(int N)
{
int res = 1;
for(int i=N;i>1;--i)
res *= i;
cout << "Result is: " << res << endl;
return res;
}
int main(int argc,char** argv)
{
int x;
std::future<int> fu = std::async(factorial, 4 );
x = fu.get();//get()函式會等待子執行緒結束,然後將值賦值給x.
return 0;
}
future類是可以從未來獲取某個變數的類,需要注意的是,future的get函式只能呼叫一次.如果呼叫2次則會崩潰.
此外這裡的async並不會建立一個子執行緒,取決於其第一個引數.
std::future<int> fu = std::async(std::launch::deferred, factorial, 4);
//這樣是不會建立一個執行緒的,它會延期啟動factorial函式,當執行到了get()函式,factorial()函式會在同個執行緒中呼叫.
//當把引數改為std::launch::async,則會建立一個子執行緒.
//當把引數改為std::launch::async | std::launch::deferred,則表示是否建立一個執行緒,取決與實現,這個引數也是預設引數.
future也是一種執行緒間通訊方式,它是用於主執行緒獲取子執行緒中的變數,如果我們從子執行緒中來獲取主執行緒中的變數又應該怎麼來實現呢?我們可以通過promise的類的使用,來將主執行緒的值傳遞到子執行緒中.
#include <deque>
#include <functional>
#include <iostream>
#include <fstream>
#include <thread>
#include <string>
#include <mutex>
#include <future>
using namespace std;
int factorial(std::future<int>& f)
{
int res = 1;
int N = f.get();//如果主執行緒中沒有set_value(),則會丟擲異常
for(int i=N;i>1;--i)
res *= i;
cout << "Result is: " << res << endl;
return res;
}
int main(int argc,char** argv)
{
int x;
std::promise<int> p;
std::future<int> f = p.get_future();
std::future<int> fu = std::async(std::launch::async, factorial, std::ref(f));
p.set_value(4);
x = fu.get();//get()函式會等待子執行緒結束,然後將值賦值給x.
cout << "Get from child:" << x;
return 0;
}
promise的定義就像一種承諾,如果定義就一定要對其值進行設定.而且,這裡的promise和future都不能被拷貝,只能被移動.
如果在上面這段程式碼中,我們需要建立10個執行緒,那麼我們就需要同步的建立10對的promise和future,這樣並不是很方便.因此,我們引入std::shared_future<int>型別.其中,該型別物件可以被拷貝.
#include <deque>
#include <functional>
#include <iostream>
#include <fstream>
#include <thread>
#include <string>
#include <mutex>
#include <future>
using namespace std;
int factorial(std::shared_future<int> f)
{
int res = 1;
int N = f.get();//如果主執行緒中沒有set_value(),則會丟擲異常
for(int i=N;i>1;--i)
res *= i;
cout << "Result is: " << res << endl;
return res;
}
int main(int argc,char** argv)
{
int x;
std::promise<int> p;
std::future<int> f = p.get_future();
std::shared_future<int> sf = f.share();
std::future<int> fu = std::async(std::launch::async, factorial, sf);
std::future<int> fu2 = std::async(std::launch::async, factorial, sf);
std::future<int> fu3 = std::async(std::launch::async, factorial, sf);
p.set_value(4);
x = fu.get();//get()函式會等待子執行緒結束,然後將值賦值給x.
cout << "Get from child:" << x;
return 0;
}