c++11 多线程
線程的創建
#include<thread>
void func(){}
std::thread t(func);
Join函數將會阻塞線程,直到線程函數執行結束。如果不希望線程被阻塞執行,可以調用線程的detach()方法,將線程和對象分離,當前線程不會阻塞。
線程不能賦值,但是可以移動;
std::thread t(func);
std::thread t1(std::move(t));
線程對象t將不再不代表任何線程。
注意線程對象的聲明周期,確保函數執行的過程中,thread的對象仍然是存在的??梢允褂胘oin或者detach。
線程的基本使用方法
獲取線程的id和cpu的核心
std::thread t(func);
t.get_id()--------->線程的id
std::thread::hardware_concurrency()---->cpu的核心數
線程休眠
std::this_thead::sleep_for(std::chrono::seconds(3));
線程互斥量
std::mutex:獨占的互斥量,不能遞歸使用
std::timed_mutex:帶超時的獨占互斥量,不能遞歸使用
std::recursive_mutex:遞歸互斥量,不帶超時
std::recursive_timed_mutex:帶超時的遞歸互斥量
1.std::mutex
std::mutex g_lock;
g_lock.lock();
..............
g_lock.unlock();
{
std::lock_guard<std::mutex> lg(g_lock);
}
2.遞歸獨占互斥量std::recursive_mutex
遞歸互斥量運行同一個線程多次獲得該互斥鎖,用來解決同一線程需要多次獲取互斥量時的死鎖問題。
3.帶有超時互斥量std::timed_mutex和std::recusive_timed_mutex
std:teime_mutex比std::mutex多了兩個接口:try_lock_for和try_lock_until
if(mutex.try_lock_for(timeout)
條件變量
conditon_variable,配合std::unique_lock<std::mutex> 進行wait操作。
condition_variable_any,和任意帶有lock、unlock語義的mutex搭配使用,效率比conditional_variable差很多。
1)擁有條件變量的線程獲取互斥量
2)循環檢查某個條件,如果條件不滿足,則阻塞直到條件滿足;如果滿足,繼續執行。
3)某個線程滿足條件執行完后調用notify_one或notify_all喚醒一個或者所有的等待線程。
std::lock_guard<std::mutex> locker(m_mutex);
while(IsFull())
? ? ? ? ? ? ? ?m_notFull.wait(m_mutex);
m_notEmpty.notify_one();
wait還可以接受條件:
m_notFull.wait(locker,[this]{return !IsFull()});
wait的時候會釋放鎖,但是notify,notifyall的時候會獲取鎖。
std::unique_lock它可以隨時釋放鎖。
std::unque_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker,[this]{return !m_queue.empty();});
?
原子量
std::atomic<int> value;
?
call_once/once_flag的使用
call_once確保在多線程情況下,被調用一次。
std::once_flag flag;
void do_once(){
? std::call_once(flag,[](){std::cout<<"Called once");
}
異步操作
std::future->作為異步結果的傳輸通道;
std::promise->將數據和future綁定起來,方便線程賦值。
std::package_task用來包裝一個可調用對象,將函數和future綁定起來,方便異步調用。
std:future
獲取線程的指向結果,通過查詢future的狀態來獲取異步操作的結果。future只能move不能拷貝,如果放到容器,必須使用shared_future
future_status有如下的3種狀態:
1.deferred,異步還沒有開始
2.Ready,異步操作已經完成
3.Timeout,異步操作超時
status =future_wait_for(std::chrono::seconds(1));
std::future_status status;
std::promise
std::promise<int> pr;
std::thread t([](std::promise<int>& p){p.set_value_at_thread_exit(9);}, std::ref(pr));
std::future<int> f=pr.get_future();
auto r=f.get();
std::package_task
包裝了一個可調用對象的包裝類(如function/lambda/bind),將函數和future綁定,以便異步調用,promise保存了一個共享狀態的值。
std::packaged_task<int()> task([](){return 7});
std::thread t1(std::ref(task));
std::futrue<int> f1=task.get_future();
auto r1=f1.get();
線程異步操作函數async
std::async比std::promise更高一層,異步任務返回的結果保存在future中,當需要獲取異步任務的是,需要調用future.get(),如果僅僅等待執行完成,調用future.wait
有兩種策略:
std::launch::async:調用async的時候開始創建線程
std::launch::defered:延遲加載方式線程,調用async時不創建線程,直到線程get或者wait時才創建線程。
?
std::future<int> f1=std::async(std::launch::async,[](){});
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: c++11-type_traits类型萃
- 下一篇: c++11 chrono