C++11中头文件thread的使用
C++11中加入了<thread>頭文件,此頭文件主要聲明了std::thread線程類(lèi)。C++11的標(biāo)準(zhǔn)類(lèi)std::thread對(duì)線程進(jìn)行了封裝。std::thread代表了一個(gè)線程對(duì)象。應(yīng)用C++11中的std::thread便于多線程程序的移值。
<thread>是C++標(biāo)準(zhǔn)程序庫(kù)中的一個(gè)頭文件,定義了C++11標(biāo)準(zhǔn)中的一些表示線程的類(lèi)、用于互斥訪問(wèn)的類(lèi)與方法等。
類(lèi)std::thread表示一個(gè)線程。初始化時(shí)給出該線程的執(zhí)行函數(shù)(或是可以調(diào)用的對(duì)象)。線程對(duì)象構(gòu)造后即開(kāi)始運(yùn)行。默認(rèn)情況下,C++11的子線程必須與主線程會(huì)合,即在主線程中調(diào)用thread::join()函數(shù),這避免了子線程還在執(zhí)行,主線程已經(jīng)執(zhí)行結(jié)束而撤銷(xiāo)的情況。
如果子線程的執(zhí)行函數(shù)需要參數(shù),可把實(shí)參列表寫(xiě)在std::thread對(duì)象構(gòu)造函數(shù)的參數(shù)列表中。如果把可調(diào)用對(duì)象(callable object)作為參數(shù)傳給子線程的構(gòu)造函數(shù),則把該可調(diào)用對(duì)象復(fù)制一份給子線程。如果需要傳遞可調(diào)用對(duì)象的左值引用給子線程,則采用std::ref()來(lái)產(chǎn)生對(duì)象的引用、然后把引用值再傳進(jìn)去給子線程。
C++11所定義的線程是和操作系統(tǒng)的線程一一對(duì)應(yīng)的,也就是說(shuō)我們生成的線程都是直接接受操作系統(tǒng)的調(diào)度的,一個(gè)進(jìn)程所能創(chuàng)建的線程數(shù)目以及一個(gè)操作系統(tǒng)所能創(chuàng)建的總的線程數(shù)據(jù)等都由運(yùn)行時(shí)操作系統(tǒng)限定。
std::thread中主要聲明三類(lèi)函數(shù):(1)、構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)(拷貝構(gòu)造函數(shù)被禁用,意味著thread不可被拷貝構(gòu)造,但能被轉(zhuǎn)移(move)或者互換(swap))及析構(gòu)函數(shù);(2)、成員函數(shù);(3)、靜態(tài)成員函數(shù)(hardware_concurrency,檢測(cè)硬件并發(fā)特性, Returns the number of hardware thread contexts)。
std::thread類(lèi)成員函數(shù):
(1)、get_id:獲取線程ID,返回一個(gè)類(lèi)型為std::thread::id的對(duì)象。
(2)、joinable:檢查線程是否可被join。檢查thread對(duì)象是否標(biāo)識(shí)一個(gè)活動(dòng)(active)的可行性線程。缺省構(gòu)造的thread對(duì)象、已經(jīng)完成join的thread對(duì)象、已經(jīng)detach的thread對(duì)象都不是joinable。
(3)、join:調(diào)用該函數(shù)會(huì)阻塞當(dāng)前線程。阻塞調(diào)用者(caller)所在的線程直至被join的std::thread對(duì)象標(biāo)識(shí)的線程執(zhí)行結(jié)束。
(4)、detach:將當(dāng)前線程對(duì)象所代表的執(zhí)行實(shí)例與該線程對(duì)象分離,使得線程的執(zhí)行可以單獨(dú)進(jìn)行。一旦線程執(zhí)行完畢,它所分配的資源將會(huì)被釋放。
(5)、native_handle:該函數(shù)返回與std::thread具體實(shí)現(xiàn)相關(guān)的線程句柄。native_handle_type是連接thread類(lèi)和操作系統(tǒng)SDK API之間的橋梁,如在Linux g++(libstdc++)里,native_handle_type其實(shí)就是pthread里面的pthread_t類(lèi)型,當(dāng)thread類(lèi)的功能不能滿(mǎn)足我們的要求的時(shí)候(比如改變某個(gè)線程的優(yōu)先級(jí)),可以通過(guò)thread類(lèi)實(shí)例的native_handle()返回值作為參數(shù)來(lái)調(diào)用相關(guān)的pthread函數(shù)達(dá)到目錄。This member function is only present in class thread if the library implementation supports it. If present, it returns a value used to access implementation-specific information associated to the thread.
(6)、swap:交換兩個(gè)線程對(duì)象所代表的底層句柄。
(7)、operator=:moves the thread object
(8)、hardware_concurrency:靜態(tài)成員函數(shù),返回當(dāng)前計(jì)算機(jī)最大的硬件并發(fā)線程數(shù)目。基本上可以視為處理器的核心數(shù)目。
另外,std::thread::id表示線程ID,定義了在運(yùn)行時(shí)操作系統(tǒng)內(nèi)唯一能夠標(biāo)識(shí)該線程的標(biāo)識(shí)符,同時(shí)其值還能指示所標(biāo)識(shí)的線程的狀態(tài)。Values of this type are returned by thread::get_id and this_thread::get_id to identify threads.
有時(shí)候我們需要在線程執(zhí)行代碼里面對(duì)當(dāng)前調(diào)用者線程進(jìn)行操作,針對(duì)這種情況,C++11里面專(zhuān)門(mén)定義了一個(gè)命名空間this_thread,此命名空間也聲明在<thread>頭文件中,其中包括get_id()函數(shù)用來(lái)獲取當(dāng)前調(diào)用者線程的ID;yield()函數(shù)可以用來(lái)將調(diào)用者線程跳出運(yùn)行狀態(tài),重新交給操作系統(tǒng)進(jìn)行調(diào)度,即當(dāng)前線程放棄執(zhí)行,操作系統(tǒng)調(diào)度另一線程繼續(xù)執(zhí)行;sleep_until()函數(shù)是將線程休眠至某個(gè)指定的時(shí)刻(time point),該線程才被重新喚醒;sleep_for()函數(shù)是將線程休眠某個(gè)指定的時(shí)間片(time span),該線程才被重新喚醒,不過(guò)由于線程調(diào)度等原因,實(shí)際休眠實(shí)際可能比sleep_duration所表示的時(shí)間片更長(zhǎng)。
std::thread:Class to represent individual threads of execution. A thread of execution is a sequence of instructions that can be executed concurrently with other such sequences in multithreading environments, while sharing a same address space.
std::this_thread:This namespace groups a set of functions that access the current thread.
下面是從其他文章中copy的<thread>測(cè)試代碼,詳細(xì)內(nèi)容介紹可以參考對(duì)應(yīng)的reference:
#include "thread2.hpp"
#include <iostream>
#include <vector>
#include <functional>
#include <memory>
#include <list>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <thread>
#include <chrono>
#include <iomanip>
#include <ctime>
#include <algorithm>namespace thread_ {std::atomic<int> global_counter(0);#ifdef _MSC_VER///
// reference: http://www.cplusplus.com/reference/thread/thread/thread/static void increase_global(int n) { for (int i = 0; i<n; ++i) ++global_counter; }static void increase_reference(std::atomic<int>& variable, int n) { for (int i = 0; i<n; ++i) ++variable; }struct C : std::atomic<int> {C() : std::atomic<int>(0) {}void increase_member(int n) { for (int i = 0; i<n; ++i) fetch_add(1); }
};int test_thread_thread()
{// thread::thread: Constructs a thread objectstd::vector<std::thread> threads;std::cout << "increase global counter with 10 threads...\n";for (int i = 1; i <= 10; ++i)threads.push_back(std::thread(increase_global, 1000));std::cout << "increase counter (foo) with 10 threads using reference...\n";std::atomic<int> foo(0);for (int i = 1; i <= 10; ++i)threads.push_back(std::thread(increase_reference, std::ref(foo), 1000));std::cout << "increase counter (bar) with 10 threads using member...\n";C bar;for (int i = 1; i <= 10; ++i)threads.push_back(std::thread(&C::increase_member, std::ref(bar), 1000));std::cout << "synchronizing all threads...\n";for (auto& th : threads) th.join();std::cout << "global_counter: " << global_counter << '\n';std::cout << "foo: " << foo << '\n';std::cout << "bar: " << bar << '\n';return 0;
}// reference: http://www.cplusplus.com/reference/thread/thread/detach/
static void pause_thread(int n)
{std::this_thread::sleep_for(std::chrono::seconds(n));std::cout << "pause of " << n << " seconds ended\n";
}int test_thread_detach()
{// thread::detach: Detaches the thread represented by the object from the calling thread,// allowing them to execute independently from each other.std::cout << "Spawning and detaching 3 threads...\n";std::thread(pause_thread, 1).detach();std::thread(pause_thread, 2).detach();std::thread(pause_thread, 3).detach();std::cout << "Done spawning threads.\n";std::cout << "(the main thread will now pause for 5 seconds)\n";// give the detached threads time to finish (but not guaranteed!):pause_thread(5);return 0;
}//
// reference: http://www.cplusplus.com/reference/thread/thread/get_id/
std::thread::id main_thread_id = std::this_thread::get_id();static void is_main_thread()
{// this_thread::get_id: Returns the thread id of the calling thread.// This value uniquely identifies the thread.if (main_thread_id == std::this_thread::get_id())std::cout << "This is the main thread.\n";elsestd::cout << "This is not the main thread.\n";
}int test_thread_get_id()
{// thread::get_id: Returns the thread id// If the thread object is joinable, the function returns a value that uniquely identifies the thread.// If the thread object is not joinable, the function returns a default - constructed object of member type thread::id.is_main_thread();std::thread th(is_main_thread);th.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/thread/thread/join/
int test_thread_join()
{// thread::join: The function returns when the thread execution has completed.std::cout << "Spawning 3 threads...\n";std::thread t1(pause_thread, 1);std::thread t2(pause_thread, 2);std::thread t3(pause_thread, 3);std::cout << "Done spawning threads. Now waiting for them to join:\n";t1.join();t2.join();t3.join();std::cout << "All threads joined!\n";return 0;
}///
// reference: http://www.cplusplus.com/reference/thread/thread/joinable/
static void mythread()
{// do stuff...
}int test_thread_joinable()
{// thread::joinable: Returns whether the thread object is joinable.// A thread object is joinable if it represents a thread of execution.std::thread foo; // 缺省構(gòu)造函數(shù),線程不可執(zhí)行std::thread bar(mythread);std::cout << "Joinable after construction:\n" << std::boolalpha;std::cout << "foo: " << foo.joinable() << '\n';std::cout << "bar: " << bar.joinable() << '\n';if (foo.joinable()) foo.join();if (bar.joinable()) bar.join();std::cout << "Joinable after joining:\n" << std::boolalpha;std::cout << "foo: " << foo.joinable() << '\n';std::cout << "bar: " << bar.joinable() << '\n';return 0;
}//
// reference: http://www.cplusplus.com/reference/thread/thread/operator=/
int test_thread_operator()
{// thread::operator=: Move-assign thread// If the object is currently not joinable, it acquires the thread of execution represented by rhs(if any).// If it is joinable, terminate() is called.// After the call, rhs no longer represents any thread of execution(as if default - constructed).std::thread threads[5]; // default-constructed threadsstd::cout << "Spawning 5 threads...\n";for (int i = 0; i<5; ++i)threads[i] = std::thread(pause_thread, i + 1); // move-assign threadsstd::cout << "Done spawning threads. Now waiting for them to join:\n";for (int i = 0; i<5; ++i)threads[i].join();std::cout << "All threads joined!\n";return 0;
}//
// reference: http://www.cplusplus.com/reference/thread/this_thread/sleep_for/
int test_this_thread_sleep_for()
{// this_thread::sleep_for: Blocks execution of the calling thread during the span of time specified by rel_time.// The execution of the current thread is stopped until at least rel_time has passed from now.// Other threads continue their execution.std::cout << "countdown:\n";for (int i = 10; i>0; --i) {std::cout << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Lift off!\n";return 0;
}/
// reference: http://www.cplusplus.com/reference/thread/this_thread/sleep_until/
int test_this_thread_sleep_until()
{// this_thread::sleep_until: Blocks the calling thread until abs_time.// The execution of the current thread is stopped until at least abs_time, while other threads may continue to advance.using std::chrono::system_clock;std::time_t tt = system_clock::to_time_t(system_clock::now());struct std::tm * ptm = std::localtime(&tt);
#ifdef _MSC_VERstd::cout << "Current time: " << std::put_time(ptm, "%X") << '\n';
#endifstd::cout << "Waiting for the next minute to begin...\n";++ptm->tm_min; ptm->tm_sec = 0;std::this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
#ifdef _MSC_VERstd::cout << std::put_time(ptm, "%X") << " reached!\n";
#endifreturn 0;
}/
// reference: http://www.cplusplus.com/reference/thread/this_thread/yield/
std::atomic<bool> ready(false);static void count1m(int id)
{while (!ready) { // wait until main() sets ready...std::this_thread::yield();}for (volatile int i = 0; i<1000000; ++i) {}std::cout << id << std::endl;
}int test_this_thread_yield()
{// this_thread::yield: The calling thread yields, offering the implementation the opportunity to reschedule.// This function shall be called when a thread waits for other threads to advance without blocking.std::thread threads[10];std::cout << "race of 10 threads that count to 1 million:\n";for (int i = 0; i<10; ++i) threads[i] = std::thread(count1m, i);ready = true; // go!for (auto& th : threads) th.join();std::cout << '\n';return 0;
}//
// reference: https://zh.wikibooks.org/zh-hans/C%2B%2B/STL/Thread
template<typename T>
class SyncQueue {
public:SyncQueue(int maxSize) :m_maxSize(maxSize), m_needStop(false) {}void Put(const T&x) { Add(x); }void Put(T&&x) { Add(std::forward<T>(x)); }void Take(std::list<T>& list){std::unique_lock<std::mutex> locker(m_mutex);m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });if (m_needStop) return;list = std::move(m_queue);m_notFull.notify_one();}void Take(T& t){std::unique_lock<std::mutex> locker(m_mutex);m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });if (m_needStop) return;t = m_queue.front();m_queue.pop_front();m_notFull.notify_one();}void Stop(){{std::lock_guard<std::mutex> locker(m_mutex);m_needStop = true;}m_notFull.notify_all();m_notEmpty.notify_all();}bool Empty(){std::lock_guard<std::mutex> locker(m_mutex);return m_queue.empty();}bool Full(){std::lock_guard<std::mutex> locker(m_mutex);return m_queue.size() == m_maxSize;}size_t Size(){std::lock_guard<std::mutex> locker(m_mutex);return m_queue.size();}int Count(){return m_queue.size();}private:bool NotFull() const{bool full = m_queue.size() >= m_maxSize;if (full)std::cout << "full, waiting, thread id: " << std::this_thread::get_id() << std::endl;return !full;}bool NotEmpty() const{bool empty = m_queue.empty();if (empty)std::cout << "empty,waiting, thread id: " << std::this_thread::get_id() << std::endl;return !empty;}template<typename F>void Add(F&&x){std::unique_lock< std::mutex> locker(m_mutex);m_notFull.wait(locker, [this] {return m_needStop || NotFull(); });if (m_needStop) return;m_queue.push_back(std::forward<F>(x));m_notEmpty.notify_one();}private:std::list<T> m_queue; //緩沖區(qū)std::mutex m_mutex; //互斥量和條件變量結(jié)合起來(lái)使用std::condition_variable m_notEmpty;//不為空的條件變量std::condition_variable m_notFull; //沒(méi)有滿(mǎn)的條件變量int m_maxSize; //同步隊(duì)列最大的sizebool m_needStop; //停止的標(biāo)志
};const int MaxTaskCount = 100;
class ThreadPool {
public:using Task = std::function<void()>;ThreadPool(int numThreads = std::thread::hardware_concurrency()) : m_queue(MaxTaskCount){Start(numThreads);}~ThreadPool(void){//如果沒(méi)有停止時(shí)則主動(dòng)停止線程池Stop();}void Stop(){std::call_once(m_flag, [this] {StopThreadGroup(); }); //保證多線程情況下只調(diào)用一次StopThreadGroup}void AddTask(Task&&task){m_queue.Put(std::forward<Task>(task));}void AddTask(const Task& task){m_queue.Put(task);}private:void Start(int numThreads){m_running = true;//創(chuàng)建線程組for (int i = 0; i <numThreads; ++i) {m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));}}void RunInThread(){while (m_running) {//取任務(wù)分別執(zhí)行std::list<Task> list;m_queue.Take(list);for (auto& task : list) {if (!m_running)return;task();}}}void StopThreadGroup(){m_queue.Stop(); //讓同步隊(duì)列中的線程停止m_running = false; //置為false,讓內(nèi)部線程跳出循環(huán)并退出for (auto thread : m_threadgroup) { //等待線程結(jié)束if (thread)thread->join();}m_threadgroup.clear();}std::list<std::shared_ptr<std::thread>> m_threadgroup; //處理任務(wù)的線程組SyncQueue<Task> m_queue; //同步隊(duì)列std::atomic_bool m_running; //是否停止的標(biāo)志std::once_flag m_flag;
};void TestThdPool()
{ThreadPool pool; bool runing = true;std::thread thd1([&pool, &runing] {while (runing) {std::cout << "produce " << std::this_thread::get_id() << std::endl;pool.AddTask([] {std::cout << "consume " << std::this_thread::get_id() << std::endl;});}});std::this_thread::sleep_for(std::chrono::seconds(10));runing = false;pool.Stop();thd1.join();getchar();
}int test_thread_pool()
{TestThdPool();return 0;
}//
int test_thread_hardware_concurrency()
{std::cout << " the number of hardware thread contexts: " << std::thread::hardware_concurrency() << std::endl;return 0;
}#endif//
// reference: https://thispointer.com/c-11-multithreading-part-1-three-different-ways-to-create-threads/// creating a thread using function objects
class DisplayThread {
public:void operator()() {for (int i = 0; i < 10; ++i)std::cout<<"Display Thread Executing"<<std::endl;}
};int test_thread_1()
{std::thread threadObj((DisplayThread()));for (int i = 0; i < 10; ++i)std::cout<<"Display From Main Thread "<<std::endl;std::cout<<"Waiting For Thread to complete"<<std::endl;threadObj.join();std::cout<<"Exiting from Main Thread"<<std::endl;return 0;
}// reference: https://thispointer.com/c-11-multithreading-part-1-three-different-ways-to-create-threads/// creating a thread using lambda functions
int test_thread_2()
{int x = 9;std::thread threadObj([]{for(int i = 0; i < 10; i++)std::cout<<"Display Thread Executing"<<std::endl;});for(int i = 0; i < 10; i++)std::cout<<"Display From Main Thread"<<std::endl;threadObj.join();std::cout<<"Exiting from Main Thread"<<std::endl;return 0;
}// reference: https://stackoverflow.com/questions/10673585/start-thread-with-member-function// start thread with member function
class bar {
public:void foo() {std::cout << "hello from member function" << std::endl;}
};int test_thread_3()
{std::thread t(&bar::foo, bar());t.join();return 0;
}bool flag1 = true, flag2 = true;void print_xxx()
{while (1) {if (!flag1) break;std::this_thread::sleep_for(std::chrono::seconds(1));fprintf(stdout, "print xxx\n");}
}void print_yyy()
{while (1) {if (!flag2) break;std::this_thread::sleep_for(std::chrono::seconds(2));fprintf(stdout, "print yyy\n");}
}int test_thread_4()
{std::thread th1(print_xxx);std::thread th2(print_yyy);std::this_thread::sleep_for(std::chrono::minutes(2));flag1 = false;flag2 = false;th1.join();th2.join();return 0;
}} // namespace::thread_
?
GitHub:https://github.com/fengbingchun/Messy_Test
?
?
總結(jié)
以上是生活随笔為你收集整理的C++11中头文件thread的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 概率论中均值、方差、标准差介绍及C++/
- 下一篇: C++11中头文件atomic的使用