1 創建線程
這裏我們直接使用C++11提供的庫函數來進行實現。
簡單示例代碼如下:
#include<iostream>
#include<thread>
using namespace std;
void workFun()
{
for (int n = 0; n < 4; n++)
cout << "Hello,other thread." << endl;
}//搶佔式
int main()
{
thread t(workFun);
t.detach();
//t.join();
for (int n = 0; n < 4; n++)
cout << "Hello,main thread." << endl;
while (true)
{
}
return 0;
}
需要注意的幾個點:
- main線程結束,整個進程執行結束,其它附屬線程也隨之結束。
- 使用join()的話,主線程會等其它線程執行完才繼續執行;而使用detach()則並行執行。
2 傳遞參數給線程入口函數
測試代碼如下:
#include<iostream>
#include<thread>
using namespace std;
void workFun(int index)
{
for (int n = 0; n < 4; n++)
cout << index << "Hello,other thread." << endl;
}//搶佔式
int main()
{
thread t[4];
for (int n = 0; n < 4; n++)
{
t[n] = thread(workFun,n);
}
for (int n = 0; n < 4; n++)
{
t[n].join();
//t[n].detach();
}
for (int n = 0; n < 4; n++)
cout << "Hello,main thread." << endl;
while (true)
{
}
return 0;
}
對於線程數組來說,我們使用join各個線程之間是可以並行運行的。如果有多個線程對象,我們只調用了一個線程對象的join方法,那麼所有的線程都會以join的方式執行,就表現爲並行執行。但是,在程序執行結束前所有的線程對象都需要調用一次join方法(只能調用一次),否則程序會出現異常。
3 鎖與臨界區
在上面的代碼中我們多個線程中,cout屬於共享資源,在輸出的時候很容易出問題。我們這裏使用一下鎖,保證共享資源的安全性。代碼如下:
#include<iostream>
#include<thread>
using namespace std;
void workFun(int index)
{
for (int n = 0; n < 4; n++)
cout << index << "Hello,other thread." << endl;
}//搶佔式
int main()
{
thread t[4];
for (int n = 0; n < 4; n++)
{
t[n] = thread(workFun,n);
}
for (int n = 0; n < 4; n++)
{
t[n].join();
//t[n].detach();
}
for (int n = 0; n < 4; n++)
{
//臨界區域-開始
m.lock();
cout << "Hello,main thread." << endl;
m.unlock();
//臨界區域-結束
}
while (true)
{
}
return 0;
}
4 自解鎖
爲了防止上鎖後沒解鎖,於是誕生了自解鎖,原理和智能指針類似。
示例代碼:
mutex m;
int sum = 0;
void workFun(int index)
{
for (int n = 0; n < 20000000; n++)
{
//自解鎖
lock_guard<mutex> lg(m);
//臨界區域-開始
//m.lock();
sum++;
//m.unlock();
//臨界區域-結束
}
}//搶佔式
自解鎖源碼:
// CLASS TEMPLATE lock_guard
template <class _Mutex>
class lock_guard { // class with destructor that unlocks a mutex
public:
using mutex_type = _Mutex;
explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
_MyMutex.lock();
}
lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) { // construct but don't lock
}
~lock_guard() noexcept {
_MyMutex.unlock();
}
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
_Mutex& _MyMutex;
};
5 原子操作
對於一些基本類型,我們可以將其定義爲原子類型,避免作爲共享資源運算時需要使用鎖。原子類型相對於鎖,性能有很大的提升。
示例代碼如下:
#include<iostream>
#include<thread>
#include<mutex>//鎖
#include<atomic>//原子
#include"CELLTimestamp.hpp"
using namespace std;
//原子操作 原子 分子
mutex m;
const int tCount = 4;
atomic_int sum = 0;
void workFun(int index)
{
for (int n = 0; n < 20000000; n++)
{
//自解鎖
//lock_guard<mutex> lg(m);
//臨界區域-開始
//m.lock();
sum++;
//m.unlock();
//臨界區域-結束
}//線程安全 線程不安全
//原子操作 計算機處理命令時最小的操作單位
//cout << index << "Hello,main thread." << n << endl;
}//搶佔式
int main()
{
thread t[tCount];
for (int n = 0; n < tCount; n++)
{
t[n] = thread(workFun, n);
}
CELLTimestamp tTime;
for (int n = 0; n < tCount; n++)
{
t[n].join();
//t[n].detach();
}
cout << tTime.getElapsedTimeInMilliSec() << ",sum=" << sum << endl;
sum = 0;
tTime.update();
for (int n = 0; n < 80000000; n++)
{
sum++;
}
cout << tTime.getElapsedTimeInMilliSec() << ",sum=" << sum << endl;
cout << "Hello,main thread." << endl;
return 0;
}
參考資料: