[TOC](多線程) # 介紹: C++ 是一種支持多線程編程的編程語言,它提供了豐富的多線程支持來充分利用現代多核處理器的性能。 C++ 多線程編程通常使用標準庫中的 頭文件以及其他相關的標準庫組件來實現。 # 理論: 1. 常用的類: std::thread 類,用於創建和管理線程等等 std: ...
目錄
介紹:
C++ 是一種支持多線程編程的編程語言,它提供了豐富的多線程支持來充分利用現代多核處理器的性能。
C++ 多線程編程通常使用標準庫中的
理論:
-
常用的類:
std::thread 類,用於創建和管理線程等等
std::this_thread 命名空間中的函數來處理線程的等待和分離等等
互斥鎖(std::mutex)、條件變數(std::condition_variable)和原子操作(std::atomic) -
線程池:
線程池是一種管理和復用線程的技術,以避免頻繁創建和銷毀線程。C++ 標準庫中沒有直接提供線程池的實現,但你可以使用第三方庫或自己編寫一個簡單的線程池。 -
請註意,多線程編程可能會引入一些複雜性和潛在的問題,如競態條件和死鎖。因此,確保充分理解多線程編程的概念和最佳實踐,並使用適當的同步機制來確保線程安全是非常重要的。
案例:
std::thread:
join() //阻塞當前線程,直到目標線程執行完畢。
detach() //將線程分離,使其成為後臺線程,不再受到 join() 的控制。
//創建互斥鎖,併在訪問共用資源之前進行鎖定。
std::mutex mtx;
mtx.lock(); // 鎖定互斥鎖
// 訪問共用資源
mtx.unlock(); // 解鎖互斥鎖
//自動管理鎖的生命周期,以確保在離開作用域時自動釋放鎖。
std::mutex mtx;
{
std::lock_guard<std::mutex> lock(mtx); // 自動鎖定和解鎖
// 訪問共用資源
} // 離開作用域時自動解鎖
//條件變數用於線上程之間進行通信和同步。它們允許一個線程等待另一個線程發出的通知,以執行某些操作。
std::condition_variable cv;
// 線程1等待通知
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock); // 阻塞線程1,直到收到通知
// 線程2發送通知
cv.notify_one(); // 通知線程1
//原子操作:
std::atomic<int> counter(0);
counter.fetch_add(1, std::memory_order_relaxed); // 原子遞增操作
//案例1:
#include <iostream>
#include <thread>
void myFunction() {
// 線程1執行的代碼
}
void myFunction1(int value) {
// 線程2執行的代碼
}
int main() {
std::thread t1(myFunction); // 創建新線程並啟動
std::thread t2(myFunction1,100); // 創建新線程並啟動
t1.join(); // 等待線程完成
t2.join(); // 等待線程完成
return 0;
}
//案例2:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void myFunction(int& counter) {
for (int i = 0; i < 1000; ++i) {
std::lock_guard<std::mutex> lock(mtx); // 使用互斥鎖保護共用資源
counter++;
}
}
int main() {
int counter = 0;
std::thread t1(myFunction, std::ref(counter));
std::thread t2(myFunction, std::ref(counter));
t1.join();
t2.join();
std::cout << "Counter: " << counter << std::endl;//Counter: 2000
return 0;
}
生產者-消費者問題:
這就有意思多了,多看多吸收,多悟
不理解得就多問問Chatjpt。
//一對一:
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cv;
void producer() {
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 鎖定互斥鎖以保護共用資源
{
std::lock_guard<std::mutex> lock(mtx);
buffer.push(i);
std::cout << "Produced: " << i << std::endl;
}
// 通知消費者線程有新數據可用
cv.notify_one();
}
}
void consumer() {
for (int i = 0; i < 10; ++i) {
// 鎖定互斥鎖,等待條件變數通知
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return !buffer.empty(); });
// 消費數據
int data = buffer.front();
buffer.pop();
// 解鎖互斥鎖
lock.unlock();
std::cout << "Consumed: " << data << std::endl;
}
}
int main() {
std::thread producerThread(producer);
std::thread consumerThread(consumer);
producerThread.join();
consumerThread.join();
return 0;
}
//一對多:
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <vector>
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cv;
const int numProducers = 3; // 多個生產者線程
void producer(int id) {
for (int i = 0; i < 5; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
{
std::lock_guard<std::mutex> lock(mtx);
int data = id * 100 + i;
buffer.push(data);
std::cout << "Producer " << id << " produced: " << data << std::endl;
}
cv.notify_one();
}
}
void consumer() {
for (int i = 0; i < 15; ++i) { // 總共消費 15 個數據項
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return !buffer.empty(); }); // 等待緩衝區非空
int data = buffer.front();
buffer.pop();
lock.unlock();
std::cout << "Consumer consumed: " << data << std::endl;
}
}
int main() {
std::vector<std::thread> producerThreads;
for (int i = 0; i < numProducers; ++i) {
producerThreads.push_back(std::thread(producer, i));
}
std::thread consumerThread(consumer);
for (std::thread& thread : producerThreads) {
thread.join();
}
consumerThread.join();
return 0;
}
//多對多
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <vector>
std::queue<int> buffer; // 緩衝區隊列
std::mutex mtx; // 互斥鎖,用於保護共用資源
std::condition_variable cv; // 條件變數,用於線程間通信
const int numProducers = 2; // 多個生產者線程
const int numConsumers = 2; // 多個消費者線程
const int bufferSize = 10; // 緩衝區大小
void producer(int id) {
for (int i = 0; i < 5; ++i) { // 生產者每個生成 5 個數據項
std::this_thread::sleep_for(std::chrono::milliseconds(200));
{
std::unique_lock<std::mutex> lock(mtx);
// 等待緩衝區有空間可用
cv.wait(lock, []{ return buffer.size() < bufferSize; });
int data = id * 100 + i;
buffer.push(data);
std::cout << "Producer " << id << " produced: " << data << std::endl;
}
cv.notify_all(); // 通知所有等待的線程
}
}
void consumer(int id) {
for (int i = 0; i < 5; ++i) { // 消費者每個消費 5 個數據項
std::this_thread::sleep_for(std::chrono::milliseconds(200));
{
std::unique_lock<std::mutex> lock(mtx);
// 等待緩衝區非空
cv.wait(lock, []{ return !buffer.empty(); });
int data = buffer.front();
buffer.pop();
lock.unlock(); // 解鎖互斥鎖,允許其他線程進入臨界區
std::cout << "Consumer " << id << " consumed: " << data << std::endl;
}
cv.notify_all(); // 通知所有等待的線程
}
}
int main() {
std::vector<std::thread> producerThreads;
std::vector<std::thread> consumerThreads;
for (int i = 0; i < numProducers; ++i) {
// 創建生產者線程,並傳遞唯一的標識符 i
producerThreads.push_back(std::thread(producer, i));
}
for (int i = 0; i < numConsumers; ++i) {
// 創建消費者線程,並傳遞唯一的標識符 i
consumerThreads.push_back(std::thread(consumer, i));
}
for (std::thread& thread : producerThreads) {
thread.join(); // 等待生產者線程結束
}
for (std::thread& thread : consumerThreads) {
thread.join(); // 等待消費者線程結束
}
return 0;
}