
- C++基礎
- C++首頁
- C++概述
- C++環境設定
- C++基本語法
- C++註釋
- C++ Hello World
- C++省略名稱空間
- C++常量/字面量
- C++關鍵字
- C++識別符號
- C++資料型別
- C++數值資料型別
- C++字元資料型別
- C++布林資料型別
- C++變數型別
- C++變數作用域
- C++多個變數
- C++基本輸入/輸出
- C++修飾符型別
- C++儲存類
- C++運算子
- C++數字
- C++列舉
- C++引用
- C++日期和時間
- C++控制語句
- C++決策制定
- C++ if 語句
- C++ if else 語句
- C++巢狀 if 語句
- C++ switch 語句
- C++巢狀 switch 語句
- C++迴圈型別
- C++ while 迴圈
- C++ for 迴圈
- C++ do while 迴圈
- C++ foreach 迴圈
- C++巢狀迴圈
- C++ break 語句
- C++ continue 語句
- C++ goto 語句
- C++建構函式
- C++建構函式和解構函式
- C++複製建構函式
C++多執行緒
多執行緒是多工處理的一種特殊形式,而多工處理允許計算機同時執行兩個或多個程式的功能。一般來說,多工處理有兩種型別:基於程序的和基於執行緒的。
基於程序的多工處理處理程式的併發執行。基於執行緒的多工處理處理同一程式片段的併發執行。
多執行緒程式包含兩個或多個可以併發執行的部分。程式的每個部分稱為一個執行緒,每個執行緒定義一個單獨的執行路徑。
在C++ 11之前,沒有對多執行緒應用程式的內建支援。相反,它完全依賴於作業系統提供此功能。
本教程假設您正在使用Linux作業系統,我們將使用POSIX編寫多執行緒C++程式。POSIX執行緒(或Pthreads)提供可在許多類Unix POSIX系統(例如FreeBSD、NetBSD、GNU/Linux、Mac OS X和Solaris)上使用的API。
建立執行緒
以下例程用於建立一個POSIX執行緒:
#include <pthread.h> pthread_create (thread, attr, start_routine, arg)
這裡,pthread_create建立一個新執行緒並使其可執行。此例程可以從程式碼中的任何位置呼叫任意次數。以下是引數的描述:
序號 | 引數及描述 |
---|---|
1 | thread 子例程返回的新執行緒的不透明唯一識別符號。 |
2 | attr 可用於設定執行緒屬性的不透明屬性物件。您可以指定執行緒屬性物件,或使用NULL表示預設值。 |
3 | start_routine 執行緒建立後將執行的C++例程。 |
4 | arg 可以傳遞給start_routine的單個引數。它必須作為void型別的指標強制轉換傳遞。如果沒有要傳遞的引數,可以使用NULL。 |
程序可以建立的執行緒最大數量取決於實現。建立後,執行緒是同級的,可以建立其他執行緒。執行緒之間沒有隱含的層次結構或依賴關係。
終止執行緒
我們使用以下例程來終止POSIX執行緒:
#include <pthread.h> pthread_exit (status)
這裡pthread_exit用於顯式退出執行緒。通常,線上程完成其工作並且不再需要存在後,會呼叫pthread_exit()例程。
如果main()在它建立的執行緒之前完成並使用pthread_exit()退出,則其他執行緒將繼續執行。否則,當main()完成時,它們將被自動終止。
示例
此簡單的示例程式碼使用pthread_create()例程建立5個執行緒。每個執行緒列印一條“Hello World!”訊息,然後透過呼叫pthread_exit()終止。
#include <iostream> #include <cstdlib> #include <pthread.h> using namespace std; #define NUM_THREADS 5 void *PrintHello(void *threadid) { long tid; tid = (long)threadid; cout << "Hello World! Thread ID, " << tid << endl; pthread_exit(NULL); } int main () { pthread_t threads[NUM_THREADS]; int rc; int i; for( i = 0; i < NUM_THREADS; i++ ) { cout << "main() : creating thread, " << i << endl; rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i); if (rc) { cout << "Error:unable to create thread," << rc << endl; exit(-1); } } pthread_exit(NULL); }
使用-lpthread庫編譯以下程式,如下所示:
$gcc test.cpp -lpthread
現在,執行您的程式,將得到以下輸出:
main() : creating thread, 0 main() : creating thread, 1 main() : creating thread, 2 main() : creating thread, 3 main() : creating thread, 4 Hello World! Thread ID, 0 Hello World! Thread ID, 1 Hello World! Thread ID, 2 Hello World! Thread ID, 3 Hello World! Thread ID, 4
向執行緒傳遞引數
此示例演示如何透過結構體傳遞多個引數。您可以將任何資料型別傳遞給執行緒回撥,因為它指向void,如下例所示:
#include <iostream> #include <cstdlib> #include <pthread.h> using namespace std; #define NUM_THREADS 5 struct thread_data { int thread_id; char *message; }; void *PrintHello(void *threadarg) { struct thread_data *my_data; my_data = (struct thread_data *) threadarg; cout << "Thread ID : " << my_data->thread_id ; cout << " Message : " << my_data->message << endl; pthread_exit(NULL); } int main () { pthread_t threads[NUM_THREADS]; struct thread_data td[NUM_THREADS]; int rc; int i; for( i = 0; i < NUM_THREADS; i++ ) { cout <<"main() : creating thread, " << i << endl; td[i].thread_id = i; td[i].message = "This is message"; rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]); if (rc) { cout << "Error:unable to create thread," << rc << endl; exit(-1); } } pthread_exit(NULL); }
編譯並執行上述程式碼後,將產生以下結果:
main() : creating thread, 0 main() : creating thread, 1 main() : creating thread, 2 main() : creating thread, 3 main() : creating thread, 4 Thread ID : 3 Message : This is message Thread ID : 2 Message : This is message Thread ID : 0 Message : This is message Thread ID : 1 Message : This is message Thread ID : 4 Message : This is message
連線和分離執行緒
我們可以使用以下兩個例程來連線或分離執行緒:
pthread_join (threadid, status) pthread_detach (threadid)
pthread_join()子例程會阻塞呼叫執行緒,直到指定的'threadid'執行緒終止。建立執行緒時,其屬性之一定義它是可連線的還是分離的。只有作為可連線的建立的執行緒才能連線。如果將執行緒建立為分離的,則永遠無法連線它。
此示例演示如何使用Pthread join例程等待執行緒完成。
#include <iostream> #include <cstdlib> #include <pthread.h> #include <unistd.h> using namespace std; #define NUM_THREADS 5 void *wait(void *t) { int i; long tid; tid = (long)t; sleep(1); cout << "Sleeping in thread " << endl; cout << "Thread with id : " << tid << " ...exiting " << endl; pthread_exit(NULL); } int main () { int rc; int i; pthread_t threads[NUM_THREADS]; pthread_attr_t attr; void *status; // Initialize and set thread joinable pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for( i = 0; i < NUM_THREADS; i++ ) { cout << "main() : creating thread, " << i << endl; rc = pthread_create(&threads[i], &attr, wait, (void *)i ); if (rc) { cout << "Error:unable to create thread," << rc << endl; exit(-1); } } // free attribute and wait for the other threads pthread_attr_destroy(&attr); for( i = 0; i < NUM_THREADS; i++ ) { rc = pthread_join(threads[i], &status); if (rc) { cout << "Error:unable to join," << rc << endl; exit(-1); } cout << "Main: completed thread id :" << i ; cout << " exiting with status :" << status << endl; } cout << "Main: program exiting." << endl; pthread_exit(NULL); }
編譯並執行上述程式碼後,將產生以下結果:
main() : creating thread, 0 main() : creating thread, 1 main() : creating thread, 2 main() : creating thread, 3 main() : creating thread, 4 Sleeping in thread Thread with id : 0 .... exiting Sleeping in thread Thread with id : 1 .... exiting Sleeping in thread Thread with id : 2 .... exiting Sleeping in thread Thread with id : 3 .... exiting Sleeping in thread Thread with id : 4 .... exiting Main: completed thread id :0 exiting with status :0 Main: completed thread id :1 exiting with status :0 Main: completed thread id :2 exiting with status :0 Main: completed thread id :3 exiting with status :0 Main: completed thread id :4 exiting with status :0 Main: program exiting.