C 11新特性 執行緒庫相關

2021-08-03 12:21:01 字數 4239 閱讀 6706

std::thread t() 提供執行緒函式或者函式物件

t.join() 阻塞執行緒直到執行緒函式執行完畢

t.detach() 如果不希望執行緒被阻塞執行就呼叫detach(),但是這會導致執行緒和執行緒物件分離。

std::thread建立的執行緒在出了作用域之後會被析構,如果這時候執行緒函式還沒有執行完的話就會發生錯誤。

執行緒不能複製,但是可以移動

std:

:thread t(func);

std:

:thread t2(std:

:move(t));

當move之後,執行緒物件t就不再代表任何執行緒了。

執行緒還可以使用std::bind或者lambda表示式建立執行緒

std

::thread

t(std

::bind(func, 1, 2));

std::thread

t1((int

a, double

b){}

, 1, 2);

獲取當前執行緒id

std::thread t(func);

t.get_id();

執行緒休眠

std:

:this_thread

::sleep_for(std:

:chrono

::seconds(3));

std::this_thread類儲存了當前執行緒的一些資訊引數和方法

std:

:mutex

std:

:timed_mutex

std:

:recursive_mutex

std:

:recursive_timed_mutex

使用mutex的時候必須lock和unlock成對出現,為了防止有遺忘,這裡採用了類似raii的機制,即在類的建構函式中lock,而在析構函式中去unlock。使用的是lock_guard。

std:

:mutex g_lock;

std:

:lock_guard:

:mutex> locker(g_lock);

那通過以上的**就不需要擔心會忘記unlock這個步驟了,當locker在出作用域的時候會被析構,會自動呼叫unlock進行解鎖的。

遞迴鎖比起非遞迴鎖,效率會低一些。

條件變數需要和互斥量配合起來使用

condition_variable:配合std::unique_lock進行wait操作

condition_variable_any: 和任意帶有lock、unlock的mutex都可以搭配使用,比較靈活但是效率比condition_variable差。

std::unique_lock和std::lock_guard的差別在於前者可以自由地釋放mutex,而後者必須是在出作用域的時候才能釋放。

呼叫條件變數的wait()方法的時候,會先釋放掉互斥量,然後等到被其他執行緒notify的時候然後再去嘗試重新獲得mutex。

std::atomic

在多執行緒環境中,有時候為了保證某個函式只是執行一次的話,可以使用std::call_once()。

std::once_flag flag;

void do_once());}

int main()

上面的lambda表示式的行為只會執行一次。

主要有std:future, std::promise, std::package_task

std::future作為非同步結果的傳輸通道,可以獲取執行緒函式的返回值

std::future_status status;

do while(status != std::future_status

::ready)

std::promise用來包裝乙個值,將資料和future繫結起來

std:

:promise ptr;

std:

:thread t((std:

:promise &p), std:

:ref(ptr));

std:

:future f = ptr.get_future();

auto r = f.get();

std::package_task用來包裝乙個可呼叫物件,將函式和future繫結起來,以便非同步呼叫。

int func(int x) 

int main()

, 2, 3);

v.push_back(f);

}

future是不能複製的,不能放到容器裡,需要用到shared_future。

async可以用來直接建立非同步的task

async(std::launch::async|std::launch::deferred, f, args…)

第乙個引數是執行緒建立的策略,有兩種策略:async表示在呼叫函式的時候立即建立執行緒,而deferred是延遲載入建立執行緒,要到呼叫future.get()或者wait的時候才建立執行緒。

第二個引數是執行緒函式

第三個引數是執行緒函式的引數

std::future f1 = std::async(std::launch::async, ());

cout

<< f1.get() << endl;

std::future f2 = std::aysnc(std::launch:async, ());

f2.wait();

std::future future = std::async(std::launch::async, ());

std::cout

<< "waiting...\n";

std::future_status status;

do while(status != std::future_status::ready)

std::cout

<< future.get() << std::endl;

應該用std::async代替執行緒的建立

c++11的future提供了另外一種獨特的方式讓我們可以和建立的執行緒進行溝通。

promise這個類會建立空間來儲存執行緒的返回值,然後主線程再去讀這個空間就可以。

future實際上是可以理解為指向任務結果的指標,這樣子的話那麼promise就可以理解為是future和data的封裝。

packaged_task是將函式物件和future封裝在一起的

async可以同步/非同步建立執行緒,函式的返回值是std::future的,那麼就可以得到該執行緒的執行結果了。

#include 

#include

#include

/* this code is for future,promise,packaged_task and async

*/int main()

, std::ref(prom)).detach();

std::future f1 = prom.get_future();

std::cout

<< f1.get() << std::endl;

std::cout

<< "packaged_task: "

<< std::endl;

std::packaged_task task(

(int x)x->int);

std::future f2 = task.get_future();

std::thread(std::move(task), 2).detach();

std::cout

<< f2.get() << std::endl;

std::cout

<< "async :"

<< std::endl;

std::future f3 = std::async(std::launch::async, ()->int);

std::future_status status;

while(1)

std::cout

<< f3.get() << std::endl;

return

0;}

C 標準庫 C 11新特性

c 定義了nullptr以取代0或者null。nullptr是std nullptr t型別的 constexpr 變數。std nullptr t可以顯式或隱式地轉換為任何指標 包括類的成員函式指標 但不能顯式或隱式地轉換為任何其他型別。range based for迴圈 類似於別的語言中的for...

C 11新特性學習

lambda表示式用於建立匿名的函式物件,語法為 函式可訪問的的外部變數 函式引數 返回值型別 如 int a 1,b 2 int c b int x int b 表示函式中可以訪問外部變數b,而且引數b是按值傳遞,b 表示引數b是按引用傳遞,表示可以訪問所有外部變數,並且是用按值傳遞方式,類似,也...

C 11 新特性試用

在c 11之前,auto關鍵字用來指定儲存期。在新標準中,它的功能變為型別推斷。auto現在成了乙個型別的佔位符,通知編譯器去根據初始化 推斷所宣告變數的真實型別。各種作用域內宣告變數都可以用到它。例如,名空間中,程式塊中,或是for迴圈的初始化語句中。auto i 42 i is an int a...