《探索C 多執行緒》 future原始碼(一)

2021-07-31 07:45:40 字數 3796 閱讀 5323

在此之前的幾篇文章分別介紹和分析了c++11.0標準庫中支援多執行緒的幾個標頭檔案:、、。那麼接下來乘熱打鐵,在這篇文章中將要分析的是:多執行緒的非同步操作。

多執行緒的非同步操作原始碼在標頭檔案中。我們先來看一看中都定義了些什麼類、函式:

classes

future

future_error

packaged_task

promise

shared_future

enum classes

future_errc

future_status

launch

functions

async

future_categoy

future提供了用來訪問非同步操作結果的機制。當乙個非同步操作我們不可能馬上獲取操作結果時,就可以用同步等待的方式來獲取,通過查詢future的狀態(future_status)來獲取非同步操作結果。

future的狀態定義在future_status中,如下:

enum class future_status ;
class future中提供了幾個方法:get()、wait()、wait_for()、wait_until()。

在介紹future之前,先來介紹乙個函式:std::async。

返回future物件,其關聯的非同步狀態管理乙個函式物件。可能從概念上我們還把握不到什麼,下面看一段**:

#include // std::cout

#include // std::async, std::future

using namespace std;

// 這是乙個用於檢驗素數的函式

bool is_prime(int x)

}return true;

}int main()

else

return 0;

}

我們從**中看到,async關聯了is_prime函式且傳入引數為313222313,async返回乙個關聯了非同步狀態的future物件。在關聯完is_prime函式後,便非同步地執行main函式和is_prime函式(實際上就是兩個執行緒了)。而is_prime的返回值,可以通過future物件(**中的fut)的get()方法獲取。這裡注意,在main中呼叫fut.get(),如果is_prime函式已經執行完了,那麼可以直接獲取到其返回值;如果is_prime函式還沒有執行完,那麼將阻塞直到得到其返回值。

實際上,在std::async中的第乙個引數可以設定關聯函式的非同步啟動策略,可以設定如下:

futurefut = async(luanch::async, is_prime, 313222313);		// 1

futurefut = async(luanch::defered, is_prime, 313222313); // 2

futurefut = async(luanch::any, is_prime, 313222313); // 3

futurefut = async(luanch::sync, is_prime, 313222313); // 4

其中這四種非同步啟動策略,定義如下 ,另外在後面會我也會講解到。

// 非同步啟動的策略

enum class launch ;

講了這麼多,我們現在來總結一下std::async:

1、非同步介面std::async可以自動建立執行緒去呼叫執行緒函式,並返回乙個std::future物件,能方便的獲取執行緒的執行結果;

2、提供了函式的非同步啟動策略,可以延遲啟動。

到此為止,我們再回過頭來接著講std::future,實際上,future物件的獲取,可以通過以下三種辦法得到:

1、async

2、promise::get_future

3、packaged_task::get_future

其中方法1,我們已經在std::async中接觸過了,那麼後面的方法2、3,將在講解std::promise和std::package_task時會講到。

接下來,我們繼續分析std::future物件的幾種方法:get()、wait()、wait_for()、wait_until()。

std::future::get()

1、當共享狀態就緒時,返回值存放在共享狀態中或丟擲異常;

2、當共享狀態尚未就緒,則將阻塞執行緒並等待,直到準備就緒;

3、一旦共享狀態準備就緒,函式就不阻塞了,將會返回(或丟擲)並釋放共享狀態,使future物件不再有效,即成員函式在每個future物件的共享狀態下至多呼叫一次。

std::future::wait()

1、等待共享狀態就緒。若共享狀態尚未準備就緒,則將阻塞執行緒並等待,直到準備就緒;

2、一旦共享狀態準備就緒,函式就不阻塞了,並返回其值(既不讀取值,也不丟擲異常)。

我們來看乙個例子:

#include // std::cout

#include // std::async, std::future

#include // std::chrono::milliseconds

using namespace std;

bool is_prime (int x)

} return true;

}int main ()

std::future::wait_for()

1、在一定時間內等待共享狀態就緒;

2、如果共享狀態尚未就緒,則將阻塞執行緒並等待,直到就緒或經過設定的時間rel_time;

舉個例子:

#include // std::cout

#include // std::async, std::future

#include // std::chrono::milliseconds

bool is_prime (int x)

} return true;

}int main ()

bool x = fut.get(); // 此時能保證共享狀態已經就緒,因此get()不會阻塞

cout << "\n700020007 " << (x ? "is" : "is not") << " prime.\n";

return 0;

}

std::future::wait_until()

1、等待共享狀態就緒,直到指定的時間點到來;

2、如果共享狀態尚未就緒,則將阻塞執行緒並等待,直到就緒或指定的時間點到來。

好了,以上就是std::future的用法了。另外,我們可以注意到,在上面的**中用到了future_status::timeout來指示函式返回的原因,future_staus是乙個enum class,其定義如下:

enum class future_status ;

《探索C 多執行緒》 future原始碼(二)

std promise promise物件可以儲存某一t型別的值,該值可以被future物件 可能在另乙個執行緒中 獲取,因此promise也提供了一種同步手段。在構造時,promise物件與乙個新的共享狀態 通常是std future 相關聯,他們可以儲存t型別的值或從std exception派...

《探索C 多執行緒》 thread原始碼(二)

分析thread的內部類id 和 命名空間this thread。this thread中有四個函式,分別是 get id yield sleep for sleep until 它們的定義如下 namespace this thread thrd yield inline void sleep u...

c 多執行緒 原始碼3

在開發中經常會遇到執行緒的例子,如果某個後台操作比較費時間,我們就可以啟動乙個執行緒去執行那個費時的操作,同時程式繼續執行。在某些情況下可能會出現多個執行緒的同步協同的問題,下面的例子就展示了在兩個執行緒之間如何協同工作。這個程式的思路是共同做一件事情 從乙個arraylist中刪除元素 如果執行完...