一、多線程概述
多線程是一種利用CPU時間分片的並發編程方式,能夠提高程序的執行效率。在C++中,多線程編程需要使用一系列的線程庫來完成。除了常見的std::thread,還有boost::thread、pthread、Windows API等。
在使用多線程編程時,需要注意線程安全。多個線程同時訪問同一個資源,可能會發生讀寫衝突,導致程序異常崩潰。因此,在編寫多線程程序時,需要加鎖來避免這類問題。
下面是一個簡單的多線程程序示例:
#include <iostream>
#include <thread>
void PrintMsg(int id)
{
std::cout << "Thread " << id << " is running\n";
}
int main()
{
std::thread t1(PrintMsg, 1);
std::thread t2(PrintMsg, 2);
t1.join();
t2.join();
return 0;
}
代碼解釋:調用PrintMsg函數的兩個線程t1和t2同時啟動,分別輸出”Thread 1 is running”和”Thread 2 is running”,最後再等待這兩個線程的執行完畢。
二、線程同步
在多線程編程中,線程同步是一個非常重要的問題。線程同步指的是多個線程之間的協調和通信,以實現對共享資源的讀寫操作。
在C++中,線程同步的方式有多種,比如互斥鎖(std::mutex)、條件變數(std::condition_variable)、原子變數(std::atomic)等。
下面是一個使用std::mutex同步的例子:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex g_lock;
void PrintMsg(int id)
{
g_lock.lock();
std::cout << "Thread " << id << " is running\n";
g_lock.unlock();
}
int main()
{
std::thread t1(PrintMsg, 1);
std::thread t2(PrintMsg, 2);
t1.join();
t2.join();
return 0;
}
代碼解釋:使用std::mutex來保證PrintMsg函數的輸出不會被多個線程同時執行,從而保證線程安全。
三、線程池
線程池是一種常見的多線程編程模型,通過創建多個線程並分配工作任務的方式,來提高程序的執行效率。
C++11中也提供了線程池相關的庫,比如std::async和std::future。
下面是一個使用std::async和std::future的例子:
#include <iostream>
#include <vector>
#include <future>
int Plus(int x, int y)
{
return x + y;
}
int main()
{
std::vector<std::future<int>> futures;
for(int i = 0; i < 10; i++)
{
futures.push_back(std::async(Plus, i, i+1));
}
for(auto & f : futures)
{
std::cout << f.get() << std::endl;
}
return 0;
}
代碼解釋:將10個Plus函數的調用任務放入std::async函數中,在等待這些任務完成後,輸出結果。
四、死鎖問題
在多線程編程中,死鎖是一個常見的問題。死鎖指的是多個線程之間互相等待,導致程序無法繼續執行。
死鎖的解決方式主要有兩種:1)避免嵌套鎖;2)使用std::lock_guard來避免手動上鎖和解鎖。
下面是一個死鎖示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex g_lock1, g_lock2;
void A()
{
g_lock1.lock();
std::cout << "A locked g_lock1\n";
g_lock2.lock();
std::cout << "A locked g_lock2\n";
g_lock2.unlock();
g_lock1.unlock();
}
void B()
{
g_lock2.lock();
std::cout << "B locked g_lock2\n";
g_lock1.lock();
std::cout << "B locked g_lock1\n";
g_lock1.unlock();
g_lock2.unlock();
}
int main()
{
std::thread t1(A);
std::thread t2(B);
t1.join();
t2.join();
return 0;
}
代碼解釋:A函數先上鎖g_lock1,然後又試圖上鎖g_lock2;B函數先上鎖g_lock2,然後又試圖上鎖g_lock1,導致兩個線程之間互相等待,產生死鎖。
五、多線程性能優化
在多線程編程中,性能優化是一個非常重要的問題。性能優化可以從多個角度來進行優化,比如減少鎖競爭、提高CPU利用率、使用局部變數等。
下面是一個使用std::lock_guard和局部變數的例子來減少鎖競爭:
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
std::mutex g_lock;
void Add(std::vector<int> & v, int x)
{
std::lock_guard<std::mutex> lock(g_lock);
v.push_back(x);
}
void Worker()
{
std::vector<int> v;
for(int i = 0; i < 100000; i++)
{
Add(v, i);
}
}
int main()
{
std::vector<std::thread> threads;
for(int i = 0; i < 10; i++)
{
threads.emplace_back(Worker);
}
for(auto & t : threads)
{
t.join();
}
return 0;
}
代碼解釋:每個線程都有一個局部變數v來存儲數據,然後通過Add函數來向v中添加元素。由於每個線程有自己的局部變數,因此減少了鎖競爭的發生。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/186340.html
微信掃一掃
支付寶掃一掃