1.基礎概念
并發(Concurrency)
并發是指在同一時間段內,多個任務看起來像是同時執行的。并發并不一定意味著真正的同時執行,它可以是通過時間片輪轉等方式在多個任務之間快速切換,讓用戶感覺多個任務在同時進行。并發可以通過多線程、多進程等方式實現。
線程(Thread)
線程是進程中的一個執行單元,是 CPU 調度和分派的基本單位。一個進程可以包含多個線程,這些線程共享進程的內存空間和系統資源,但每個線程有自己獨立的棧空間和執行上下文。線程之間的通信和數據共享比進程更加方便和高效。比如,在一個瀏覽器進程中,可能會有負責渲染頁面的線程、處理網絡請求的線程等。
多線程(Multithreading)
多線程是實現并發的一種方式,它允許一個進程中同時存在多個線程,這些線程可以并行(在多核 CPU 上)或并發(在單核 CPU 上)執行不同的任務,從而提高程序的執行效率和響應速度。
進程(Process)
進程是程序在操作系統中的一次執行過程,是系統進行資源分配和調度的基本單位。每個進程都有自己獨立的內存空間、系統資源(如文件描述符等)和執行上下文。不同進程之間相互獨立,一個進程的崩潰通常不會影響其他進程。例如,當你打開一個瀏覽器、一個文本編輯器時,它們分別對應著不同的進程。(一個進程有一個主線程)
2 .操作多線程
2.1 創造線程
在 C++ 中,<thread>
?庫提供了用于管理線程的類和函數,它是 C++11 標準引入的,用于支持多線程編程
默認構建:
std::thread t;
帶執行函數的構造函數:創建一個新線程并執行指定的函數。可以傳遞參數給該函數
#include <iostream>
#include <thread>void func(int a) {std::cout << "線程執行,參數: " << a << std::endl;
}int main() {std::thread t(func, 42);t.join(); // 等待線程執行完畢return 0;
}
記得 線程只能出傳入右值
右值引用與線程
#include <iostream>
#include <thread>
#include <string>// 線程函數,接受一個字符串參數
void threadFunction(std::string str) {std::cout << "線程接收到的字符串: " << str << std::endl;
}int main() {// 使用右值引用傳遞臨時對象給線程std::thread t(threadFunction, std::string("Hello, Thread!"));// 等待線程執行完畢t.join();return 0;
}
左值引用與線程
左值引用用于引用一個已經存在的對象。在多線程編程中,如果需要在線程函數中修改外部對象,或者避免對象的拷貝,可以使用左值引用
#include <iostream>
#include <thread>
#include <string>// 線程函數,接受一個字符串的左值引用
void threadFunction(std::string& str) {str += " - Modified by thread";std::cout << "線程修改后的字符串: " << str << std::endl;
}int main() {std::string message = "Initial message";// 使用左值引用傳遞對象給線程std::thread t(threadFunction, std::ref(message));//ref提取地址// 等待線程執行完畢t.join();std::cout << "主線程看到的修改后的字符串: " << message << std::endl;return 0;
}
因為線程只能右值傳遞,所有以引用形式傳遞對象(值傳遞和引用之間的區別 你可以理解為復制和對地址操作)關于右值的話:c++新特性之 左右值 lambda 以及“for”-CSDN博客
成員函數
普通:
#include <iostream>
#include <thread>class MyClass {
public:// 普通成員函數void memberFunction(int value) {std::cout << "線程正在執行成員函數,傳入的值是: " << value << std::endl;}
};int main() {MyClass obj;int param = 42;// 創建線程并引用類的普通成員函數std::thread t(&MyClass::memberFunction, &obj, param);// 等待線程執行完畢t.join();return 0;
}
靜態:
#include <iostream>
#include <thread>class MyClass {
public:// 普通成員函數void memberFunction(int value) {std::cout << "線程正在執行成員函數,傳入的值是: " << value << std::endl;}
};int main() {MyClass obj;int param = 42;// 創建線程并引用類的普通成員函數std::thread t(&MyClass::memberFunction, &obj, param);// 等待線程執行完畢t.join();return 0;
}
2.2成員函數
join函數
join()
?函數的作用是阻塞當前線程,直到被調用?join()
?的?std::thread
?對象所代表的線程執行完畢。也就是說,當在一個線程(通常是主線程)中調用另一個線程對象的?join()
?方法時,當前線程會暫停執行,等待目標線程執行結束后才會繼續執行后續代碼。
#include <iostream>
#include <thread>// 線程函數
void threadFunction() {for (int i = 0; i < 5; ++i) {std::cout << "子線程輸出: " << i << std::endl;}
}int main() {std::thread t(threadFunction);std::cout << "主線程等待子線程執行完畢..." << std::endl;t.join(); // 主線程阻塞,等待子線程執行完畢std::cout << "子線程執行完畢,主線程繼續執行。" << std::endl;return 0;
}
detch 函數
detach()
?函數用于將?std::thread
?對象所代表的線程與該對象分離,讓線程在后臺獨立執行。分離后的線程在執行完畢后會自動釋放資源,而不需要主線程調用?join()
?來等待它結束。一旦線程被分離,就無法再通過?join()
?來等待它,也不能再使用該?std::thread
?對象來管理這個線程。
#include <iostream>
#include <thread>
#include <chrono>// 線程函數
void detachedThreadFunction() {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "分離的線程執行完畢。" << std::endl;
}int main() {std::thread t(detachedThreadFunction);std::cout << "主線程不等待分離的線程,繼續執行。" << std::endl;t.detach(); // 分離線程std::cout << "主線程繼續執行其他任務..." << std::endl;// 主線程可以繼續執行其他任務,不需要等待分離的線程return 0;
}
2.3detach陷阱
你考慮一下 上面是不是陷入陷阱?
應該是的 因為
#include <iostream>
#include <thread>
#include <chrono>// 線程函數
void detachedThreadFunction() {std::this_thread::sleep_for(std::chrono::seconds(2));//等待2s才進行std::cout << "分離的線程執行完畢。" << std::endl;
}int main() {std::thread t(detachedThreadFunction);std::cout << "主線程不等待分離的線程,繼續執行。" << std::endl;t.detach(); // 分離線程std::cout << "主線程繼續執行其他任務..." << std::endl;// 讓主線程等待足夠長的時間,確保分離的線程執行完畢std::this_thread::sleep_for(std::chrono::seconds(3)); return 0;
}
你會發現主線程已經結束了
2.4 異步執行的特性
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>void threadFunction(int id) {// 模擬線程的工作負載int i=id;if (id%2==0)id=id*3;std::this_thread::sleep_for(std::chrono::seconds(id));std::cout << "Thread " << i << " finished its work." << std::endl;
}int main() {const int numThreads = 5;std::vector<std::thread> threads;// 創建多個線程for (int i = 0; i < numThreads; ++i) {threads.emplace_back(threadFunction, i + 1);}// 等待所有線程完成for (auto& thread : threads) {thread.join();}std::cout << "All threads have finished." << std::endl;return 0;
}
//就會清晰的發現 結果
Thread 1 finished its work.
Thread 3 finished its work.
Thread 5 finished its work.
Thread 2 finished its work.
Thread 4 finished its work.
windows按工作時間來的,不是按順序!!!