1. 程式人生 > >C++之多執行緒(C++11 thread.h檔案實現多執行緒)

C++之多執行緒(C++11 thread.h檔案實現多執行緒)

轉載自:

與 C++11 多執行緒相關的標頭檔案
C++11 新標準中引入了四個標頭檔案來支援多執行緒程式設計,他們分別是<atomic> ,<thread>,<mutex>,<condition_variable>和<future>。
<atomic>:該頭文主要聲明瞭兩個類, std::atomic 和 std::atomic_flag,另外還聲明瞭一套 C 風格的原子型別和與 C 相容的原子操作的函式。
<thread>:該標頭檔案主要聲明瞭 std::thread 類,另外 std::this_thread 名稱空間也在該標頭檔案中。
<mutex>:該標頭檔案主要聲明瞭與互斥量(mutex)相關的類,包括 std::mutex 系列類,std::lock_guard, std::unique_lock, 以及其他的型別和函式。
<condition_variable>:該標頭檔案主要聲明瞭與條件變數相關的類,包括 std::condition_variable 和 std::condition_variable_any。
<future>:該標頭檔案主要聲明瞭 std::promise, std::package_task 兩個 Provider 類,以及 std::future 和 std::shared_future 兩個 Future 類,另外還有一些與之相關的型別和函式,std::async() 函式就宣告在此標頭檔案中。
demo1:thread "Hello world"

#include <stdio.h>
#include <stdlib.h>
#include <iostream> // std::cout
#include <thread>   // std::thread
void thread_task() {
    std::cout << "hello thread" << std::endl;
}
int main(int argc, const char *argv[])
{
    std::thread t(thread_task);
    t.join();//和主執行緒協同
    return EXIT_SUCCESS;
}
demo2:一次啟動多個執行緒
我們通常希望一次啟動多個執行緒,來並行工作。為此,我們可以建立執行緒組,而不是在先前的舉例中那樣建立一條執行緒。下面的例子中,主函式建立十條為一組的執行緒,並且等待這些執行緒完成他們的任務
#include <stdio.h>
#include <stdlib.h>
#include <iostream> // std::cout
#include <thread>   // std::thread
int main() {
	std::thread t[num_threads];
	//Launch a group of threads 啟動一組執行緒
	for (int i = 0; i < num_threads; ++i) {
		t[i] = std::thread(call_from_thread);
	}
	std::cout << "Launched from the mainn";
	//Join the threads with the main thread
	for (int i = 0; i < num_threads; ++i) {
		t[i].join();
	}
	return 0;
}

記住,主函式也是一條執行緒,通常叫做主執行緒,所以上面的程式碼實際上有11條執行緒在執行。在啟動這些執行緒組之後,執行緒組和主函式進行協同(join)之前,允許我們在主執行緒中做些其他的事情。
demo3:線上程中使用帶有形參的函式
#include <stdio.h>
#include <stdlib.h>
#include <iostream> // std::cout
#include <thread>   // std::thread
static const int num_threads = 10;
//This function will be called from a thread
void call_from_thread(int tid) {
    std::cout << "Launched by thread " << tid << std::endl;
}
int main() {
    std::thread t[num_threads];
    //Launch a group of threads
    for (int i = 0; i < num_threads; ++i) {
        t[i] = std::thread(call_from_thread, i);
    }
    std::cout << "Launched from the mainn";
    //Join the threads with the main thread
    for (int i = 0; i < num_threads; ++i) {
        t[i].join();
    }
	return 0;
}
執行結果:
Sol$ ./a.out


Launched by thread 0


Launched by thread 1


Launched by thread 2


Launched from the main


Launched by thread 3


Launched by thread 5


Launched by thread 6


Launched by thread 7


Launched by thread Launched by thread 4


8L


aunched by thread 9


Sol$
能看到上面的結果中,程式一旦建立一條執行緒,其執行存在先後秩序不確定的現象。程式設計師的任務就是要確保這組執行緒在訪問公共資料時不要出現阻塞。最後幾行,所顯示的錯亂輸出,表明8號執行緒啟動的時候,4號執行緒還沒有完成在stdout上的寫操作。事實上假定在你自己的機器上執行上面的程式碼,將會獲得全然不同的結果,甚至是會輸出些混亂的字元。原因在於,程式內的11條執行緒都在競爭性地使用stdout這個公共資源(案:Race Conditions)。
要避免上面的問題,可以在程式碼中使用攔截器(barriers),如std:mutex,以同步(synchronize)的方式來使得一群執行緒訪問公共資源,或者,如果可行的話,為執行緒們預留下私用的資料結構,避免使用公共資源。我們在以後的教學中,還會講到執行緒同步問題,包括使用原子操作型別(atomic types)和互斥體(mutex)。

更多內容請參考: