C++創(chuàng)建多線程的方法總結(jié)
一、多線程預(yù)備知識
多線程本質(zhì)是將程序的運(yùn)行拆分為部分,每個線程都有自己的執(zhí)行上下文,包括它的程序計(jì)數(shù)器,寄存器和棧,并且它們獨(dú)立地執(zhí)行,互不干擾。我們必須要明確的是多線程的實(shí)現(xiàn)依賴硬件條件:多線程需要多核處理器。多核處理器可以同時執(zhí)行多個線程,因此多線程可以利用多核處理器的多個內(nèi)核來實(shí)現(xiàn)更快的處理速度和更高的性能。通過使用多核處理器,可以把多個線程并行執(zhí)行,從而實(shí)現(xiàn)更高的性能和更快的處理速度。
比如說,在圖像處理應(yīng)用中,如果使用多核處理器,可以把圖像處理任務(wù)分成多個獨(dú)立的部分,并使用多個線程分別執(zhí)行每個部分。每例如,線程 1 可以處理圖像的顏色校正,線程 2 可以處理圖像的縮放,線程 3 可以處理圖像的旋轉(zhuǎn)等。由于每個線程都可以同時執(zhí)行,因此處理速度比單線程處理要快得多。需要注意的是,在這種情況下,還需要考慮線程間的同步和通信,以確保線程之間的數(shù)據(jù)一致性。
二、C++11 std::thread
2.1 創(chuàng)建線程
#include <iostream> #include <thread> void foo() { std::cout << "Hello from thread" << std::endl; } int main() { std::thread t1(foo); t1.join(); return 0; }
在上面的代碼中,通過 std::thread t1(foo)
創(chuàng)建了一個新線程,并在新線程中執(zhí)行了函數(shù) foo
。
2.2 線程管理
#include <iostream> #include <thread> void foo() { std::cout << "Hello from thread" << std::endl; } int main() { std::thread t1(foo); t1.join(); t1.detach(); return 0; }
在上面的代碼中,通過調(diào)用 t1.join()
可以等待線程 t1
結(jié)束,并通過調(diào)用 t1.detach()
可以分離線程 t1
,使線程在后臺運(yùn)行。
std::thread::detach()
方法是分離線程的方法,通過調(diào)用 detach()
方法,可以讓線程在后臺獨(dú)立運(yùn)行,不需要等待線程結(jié)束即可返回。與調(diào)用 join()
方法不同,分離的線程不受父線程的控制,因此如果父線程結(jié)束,分離的線程不會因此結(jié)束。請注意,分離的線程一旦開始執(zhí)行,它將獨(dú)立運(yùn)行,不受任何控制,因此不能在父線程中等待它的結(jié)束或者通過其他方式獲取其結(jié)果。如果需要等待線程結(jié)束,請使用 join()
方法。
分離線程的主要作用是讓線程在后臺獨(dú)立運(yùn)行,不需要等待線程結(jié)束即可返回。這樣可以在不需要等待線程結(jié)束的情況下,在父線程中執(zhí)行其他任務(wù),從而提高程序的效率。
2.3 傳遞參數(shù)
#include <iostream> #include <thread> void foo(int x) { std::cout << "Hello from thread, x = " << x << std::endl; } int main() { std::thread t1(foo, 10); t1.join(); return 0; }
在上面的代碼中,通過在創(chuàng)建線程時傳遞參數(shù) 10
,并在函數(shù) foo
中讀取參數(shù),實(shí)現(xiàn)了在線程中傳遞參數(shù)的功能。
2.4 線程間通信
2.4.1 使用共享變量和互斥量(互斥鎖):
#include <iostream> #include <thread> #include <mutex> int g_num = 0; std::mutex g_num_mutex; void print_num() { while (true) { g_num_mutex.lock(); if (g_num >= 100) { g_num_mutex.unlock(); break; } std::cout << "Thread " << std::this_thread::get_id() << ": " << g_num++ << std::endl; g_num_mutex.unlock(); } } int main() { std::thread t1(print_num); std::thread t2(print_num); t1.join(); t2.join(); return 0; }
我們定義了一個全局變量g_num,兩個線程分別運(yùn)行print_num函數(shù)。print_num函數(shù)不斷地對g_num變量進(jìn)行讀寫操作,并使用互斥量g_num_mutex對該變量進(jìn)行加鎖。這樣可以確保在每次讀寫操作時,不會有其他線程訪問g_num變量。如果g_num的值已經(jīng)大于等于100,則表示線程退出。最后主線程調(diào)用join函數(shù),等待其他線程退出。
2.4.2 使用共享內(nèi)存
#include <iostream> #include <thread> #include <string> using namespace std; string message; void write_message() { message = "Hello World"; } void read_message() { cout << message << endl; } int main() { thread t1(write_message); thread t2(read_message); t1.join(); t2.join(); return 0; }
2.5 其他線程相關(guān)信息
std::thread::hardware_concurrency()
:返回當(dāng)前系統(tǒng)支持的最大線程數(shù)。std::thread::native_handle()
:返回線程的原生句柄,在不同的平臺中可能不同。std::thread::joinable()
:判斷線程是否可以被 join,如果線程已經(jīng)結(jié)束或者被分離,則返回 false。std::thread::join()
:等待線程結(jié)束,直到線程結(jié)束才返回。std::thread::detach()
:分離線程,使線程可以在后臺運(yùn)行,并且不需要等待其結(jié)束。std::thread::get_id()
:返回線程ID。
三、boost多線程庫
官方文檔:
Boost 庫中的 boost::thread
類可以方便地創(chuàng)建和管理多線程。以下是一個使用 Boost 庫中的 boost::thread
類創(chuàng)建多線程的簡單示例:
#include <iostream> #include <boost/thread.hpp> void worker_thread() { std::cout << "Worker thread is running" << std::endl; } int main() { boost::thread worker(worker_thread); std::cout << "Main thread is running" << std::endl; worker.join(); return 0; }
四、POSIX線程(Linux&Unix)
C++ POSIX 線程(pthread)庫可以幫助您在 C++ 中創(chuàng)建和管理多線程。下面是一個創(chuàng)建和啟動一個新線程的示例代碼:
#include <pthread.h> #include <iostream> void *thread_func(void *arg) { std::cout << "Thread started with argument: " << *((int *)arg) << std::endl; return NULL; } int main() { pthread_t thread_id; int arg = 42; // 創(chuàng)建新線程 int result = pthread_create(&thread_id, NULL, thread_func, &arg); if (result != 0) { std::cerr << "Error: pthread_create() failed" << std::endl; return 1; } // 等待線程結(jié)束 result = pthread_join(thread_id, NULL); if (result != 0) { std::cerr << "Error: pthread_join() failed" << std::endl; return 1; } return 0; }
這段代碼中,pthread_create
函數(shù)用于創(chuàng)建一個新線程,并啟動它。第一個參數(shù)是一個指向線程 ID 的指針,第二個參數(shù)指定了線程的屬性,通常為 NULL
,第三個參數(shù)是線程函數(shù)的地址,最后一個參數(shù)是傳遞給線程函數(shù)的參數(shù)。
pthread_join
函數(shù)等待線程結(jié)束,第一個參數(shù)是線程 ID,第二個參數(shù)是接收線程返回值的指針,通常為 NULL
。
五、 Windows線程庫
5.1 線程使用
下面是使用Windows API創(chuàng)建線程并打印數(shù)字并獲取重要的線程信息的代碼示例:
#include <iostream> #include <Windows.h> DWORD WINAPI ThreadFunction(LPVOID lpParam) { // 獲取當(dāng)前線程ID DWORD threadId = GetCurrentThreadId(); std::cout << "Thread ID: " << threadId << std::endl; // 獲取線程傳入的參數(shù) int threadParam = *(int*)lpParam; for (int i = 0; i < threadParam; i++) { std::cout << i << std::endl; } return 0; } int main() { int num = 10; // 創(chuàng)建線程 HANDLE hThread = CreateThread(NULL, 0, ThreadFunction, &num, 0, NULL); // 等待線程結(jié)束 WaitForSingleObject(hThread, INFINITE); // 關(guān)閉線程句柄 CloseHandle(hThread); return 0; }
5.2 線程通信
在 Windows API 中,可以使用 CreateThread
函數(shù)創(chuàng)建線程,以下是通過共享變量實(shí)現(xiàn)線程間通信的代碼示例:
#include <Windows.h> #include <iostream> DWORD WINAPI ThreadFunction1(LPVOID lpParam) { int* sharedVariable = (int*)lpParam; while (true) { if (*sharedVariable == 0) { std::cout << "Thread 1: sharedVariable = " << *sharedVariable << std::endl; *sharedVariable = 1; } } return 0; } DWORD WINAPI ThreadFunction2(LPVOID lpParam) { int* sharedVariable = (int*)lpParam; while (true) { if (*sharedVariable == 1) { std::cout << "Thread 2: sharedVariable = " << *sharedVariable << std::endl; *sharedVariable = 0; } } return 0; } int main() { int sharedVariable = 0; HANDLE hThread1 = CreateThread(NULL, 0, ThreadFunction1, &sharedVariable, 0, NULL); HANDLE hThread2 = CreateThread(NULL, 0, ThreadFunction2, &sharedVariable, 0, NULL); WaitForMultipleObjects(2, &hThread1, TRUE, INFINITE); CloseHandle(hThread1); CloseHandle(hThread2); return 0; }
在主函數(shù)中,我們調(diào)用了 CreateThread
函數(shù)創(chuàng)建了兩個線程,將共享變量 sharedVariable
的地址作為參數(shù)傳入。線程 1 和線程 2 都通過判斷共享變量的值來實(shí)現(xiàn)通信,它們每當(dāng)共享變量的值變化時都會輸出當(dāng)前的值。
在這個例子中,WaitForMultipleObjects函數(shù)將等待兩個線程hThread1和hThread2完成,并且要求等待所有事件對象完成,因此參數(shù)bWaitAll的值為TRUE。并且dwMilliseconds的值為INFINITE,所以等待時間是無限的。
以上就是C++創(chuàng)建多線程的方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于C++創(chuàng)建多線程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)文件編碼格式識別
在做數(shù)據(jù)導(dǎo)入導(dǎo)出的過程中,如果應(yīng)用場景多了,相信各位都會遇到一個問題就是文件編碼的問題。本文將用Qt實(shí)現(xiàn)文件編碼格式識別,感興趣的可以了解一下2022-06-06C++小練習(xí)之高性能實(shí)現(xiàn)字符串分割
字符串分割是日常工作中比較常見的基礎(chǔ)函數(shù),通常大家會使用現(xiàn)成的基礎(chǔ)庫,基礎(chǔ)庫的性能是否是最佳的,本文主要和大家探討一下如何最大限度的提升字符串分割的性能,希望對大家有所幫助2023-10-10Qt使用隨機(jī)驗(yàn)證碼的實(shí)現(xiàn)示例
有時候在登錄界面需要驗(yàn)證碼功能,這樣能夠防止被惡意程序攻擊,本文主要介紹了Qt使用隨機(jī)驗(yàn)證碼的實(shí)現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2024-01-01