一、線程的定義
線程是計算機中最小的可執行單元,是操作系統中進行CPU調度和分配的基本單位,一個進程可以包含多個線程。不同於進程間的資源隔離,不同線程之間可以共享進程的資源,如內存、文件描述符等。線程主要包括線程標識符、程序計數器、寄存器集合、棧和線程本地存儲區域等組成部分。
二、線程的創建和銷毀
在C++11標準中,線程的創建和銷毀主要由std::thread類來實現,創建線程的基本形式如下:
#include <thread> void function_to_execute(); std::thread t(function_to_execute); //創建一個新線程
創建新線程時需要指定線程需要執行的函數名或lambda表達式,在這裡function_to_execute()為線程函數,std::thread t是線程對象。銷毀線程主要有detach()函數和join()函數,前者將線程與線程對象解綁,允許線程對象獨立運行,後者等待線程執行完成後才繼續執行主線程。
三、線程的同步
多個線程之間進行資源共享時,需要注意同步問題。引入同步機制可以防止多個線程同時對同一個資源進行訪問併產生衝突,通常採用互斥量和條件變數實現同步。在C++11標準中,互斥量(std::mutex)用於保護共享數據資源,條件變數(std::condition_variable)提供了一種等待通知的機制。
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void function1() {
std::unique_lock<std::mutex> lck(mtx);
// 同步執行
cv.wait(lck, []{return ready;});
// 繼續執行
}
void function2() {
// 準備數據
{
std::lock_guard<std::mutex> lck(mtx);
// 獲得鎖
ready = true;
}
cv.notify_one();
// 通知另一個線程
}
上面代碼中,mutex被用來保護一個boolean類型的ready變數。function1()和function2()都需要使用控制ready變數的線程同步機制來確保ready已經被設置。function1()上鎖,調用wait()函數開始等待,直到另一個線程上鎖並調用notify_one()函數來解除等待並繼續執行。function2()設置ready後,調用notify_one()函數向另一個線程通知數據已準備好。
四、線程的安全性問題
在多線程編程中,可能出現數據競爭、死鎖、飢餓、優先順序反轉等問題。其中數據競爭是典型的線程不安全問題,通常通過使用原子類型、鎖等手段來解決。原子類型是一種特殊類型,可以保證對其操作的「原子性」,即線程安全。std::atomic類提供了常用的原子類型,如std::atomic_int、std::atomic_bool等。
#include <atomic>
std::atomic_int a(0);
void increase() { a++; }
上面代碼中,std::atomic_int類的對象a可以通過該類提供的++操作進行原子遞增,從而保證多個線程之間的線程安全。
五、線程的優化
優化多線程程序的性能是程序員們需要面對的挑戰之一。線程池是一個常用的優化多線程程序的手段。線程池的本質是維護一定數量的線程,用於執行需要並發處理的任務,線程池可以避免反覆創建和銷毀線程的開銷,降低了線程創建帶來的性能影響。
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <queue>
std::queue<std::function<void()>> taskQueue;
std::mutex taskMutex;
std::condition_variable taskCV;
std::atomic_bool stop_flag(false);
void worker() {
std::function<void()> task;
while (true) {
{
std::unique_lock<std::mutex> lock(taskMutex);
taskCV.wait(lock, []{ return !taskQueue.empty() || stop_flag.load(); });
if (stop_flag && taskQueue.empty()) {
return;
} else if (!taskQueue.empty()) {
task = taskQueue.front();
taskQueue.pop();
} else {
continue;
}
}
task();
}
}
class ThreadPool {
public:
ThreadPool(size_t numThreads) {
for (size_t i = 0; i < numThreads; i++) {
workers.emplace_back(worker);
}
}
~ThreadPool() {
stop_flag = true;
taskCV.notify_all();
for (auto& worker : workers) {
worker.join();
}
}
template <typename F, typename ...Args>
auto addTask(F&& f, Args&& ...args) {
auto task = std::make_shared<std::function<void()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
std::unique_lock<std::mutex> lock(taskMutex);
taskQueue.emplace([task](){ (*task)(); });
taskCV.notify_one();
return task;
}
private:
std::vector<std::thread> workers;
};
ThreadPool pool(4);
void thread_func(int x, int y) {
for (int i = x; i < y; i++) {
printf("thread id: %d\n", std::this_thread::get_id());
printf("i = %d\n", i);
}
}
void test_thread_pool() {
for (int i = 0; i < 10; i++) {
auto task = pool.addTask(thread_func, i * 10, i * 10 + 10);
}
}
上述代碼實現了一個簡單的線程池,包括添加任務、等待任務、執行任務等基本功能。代碼通過std::thread和std::mutex等C++標準庫提供的線程相關的類和函數實現。
原創文章,作者:HWOCS,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/370022.html
微信掃一掃
支付寶掃一掃