一、多線程基礎知識
1、C++11的多線程庫
C++11標準引入了對多線程的支持,它定義了<thread>
頭文件以及std::thread
類,可以方便地進行線程創建、結束、等待等操作。下面是一個簡單的示例:
#include <iostream> #include <thread> void hello() { std::cout << "Hello World!<br>" << std::endl; } int main() { std::thread t(hello); t.join(); return 0; }
2、線程間的數據共享
多線程編程中,不同線程之間需要共享數據,但共享數據容易引起線程安全問題,需要使用互斥量std::mutex
來進行保護。
#include <iostream> #include <thread> #include <mutex> std::mutex mu; int g_count = 0; void increment() { mu.lock(); ++g_count; mu.unlock(); } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "g_count = " << g_count << std::endl; return 0; }
二、多線程優化策略
1、任務分解
將大任務分成多個小任務,每個小任務由一個線程執行,通過這種方式可以提高程序的整體處理速度。
#include <iostream> #include <thread> #include <vector> #include <cmath> const int N = 1000000; void calculate(int start, int end, double* result) { for(int i = start; i < end; ++i) { result[i] = sqrt(i); } } int main() { double* result = new double[N]; std::vector<std::thread> threads; const int thread_count = std::thread::hardware_concurrency(); const int block_size = N / thread_count; for(int i = 0; i < thread_count; ++i) { int start = i * block_size; int end = (i == thread_count-1) ? N : (i+1) * block_size; threads.push_back(std::thread(calculate, start, end, result)); } for(auto& t : threads) { t.join(); } delete[] result; return 0; }
2、避免不必要的複製
多線程程序中,有時需要傳遞大量數據到線程執行的函數中,如果直接傳遞這些數據,會造成大量的複製開銷,可以通過使用指針或引用的方式,減小函數參數的複製。
#include <iostream> #include <thread> #include <cstring> #include <cstdlib> void worker(const char* str) { char* s = (char*)malloc(sizeof(str)+1); std::strcpy(s, str); std::cout << "Thread " << std::this_thread::get_id() << " : " << s << std::endl; free(s); } int main() { const char* str = "Hello World!"; std::thread t(worker, str); t.join(); return 0; }
三、多線程應用場景
1、網絡編程
網絡編程中,需要同時處理多個客戶端的請求,通過多線程可以提高服務器的並發處理性能。
//Server代碼 #include <iostream> #include <thread> #include <chrono> #include <string> #include <cstring> #include <vector> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> const int PORT = 8888; int server_fd = 0, client_fd = 0; bool is_running = true; std::vector<std::thread> threads; void client_thread(int fd) { char buffer[1024]; struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); while(is_running) { memset(buffer, 0, sizeof(buffer)); int n = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addr_len); if(n == -1) continue; //處理客戶端請求 std::cout << "Thread " << std::this_thread::get_id() << " : receive message from " << inet_ntoa(client_addr.sin_addr) << " : " << ntohs(client_addr.sin_port) << ", message:" << buffer << std::endl; } } void init_server() { server_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); listen(server_fd, 10); std::cout << "Server start ..." << std::endl; while(is_running) { client_fd = accept(server_fd, NULL, NULL); std::thread t(client_thread, client_fd); threads.push_back(std::move(t)); } for(auto& t : threads) { if(t.joinable()) t.join(); } } void stop_server() { is_running = false; close(client_fd); close(server_fd); } int main() { std::thread t(init_server); getchar(); stop_server(); t.join(); return 0; }
2、數據處理
數據處理中,經常需要進行大量的計算、排序、查找等操作,通過多線程可以加快計算速度。
#include <iostream> #include <thread> #include <vector> #include <algorithm> #include <random> const long long N = 100000000000; const int block_size = 1000000; std::vector<std::thread> threads; double* a; void calculate(int start, int end, double* result) { for(long long i = start; i < end; ++i) { result[i] = sqrt(i); } } int main() { a = new double[N]; for(int i = 0; i < N; i += block_size) { int start = i; int end = (i + block_size < N) ? i + block_size : N; threads.push_back(std::thread(calculate, start, end, a)); } for(auto& t : threads) { t.join(); } std::sort(a, a+N); delete[] a; return 0; }
四、結語
本文介紹了C++多線程編程的基礎知識、優化策略和應用場景,但是多線程編程也有其困難和缺陷,需要開發者在使用時進行綜合考慮。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/306134.html