C++ 多執行緒 atomic
阿新 • • 發佈:2018-12-01
atomic 先上翻譯。
aotomic原子的 即不能分割的,最小單位。
舉個例子,int num;
num = num +1;
我們都知道對於num=num+1這條程式語句需要分解為三步,
1、把變數num讀取到某一個暫存器R儲存,
2、CPU對暫存器R的值進行計算,
3、計算完成後將值存回記憶體
在多執行緒執行num++的時候 當前num為1 執行緒A執行完第二步 此時num為2但是還沒有存入記憶體,然後執行緒B開始執行第一步,從記憶體中取出num,num依舊是1,這樣就出現問題了,相當於A執行緒和B執行緒一共執行了連詞num=num+1,但是num卻只增加了1,。
我們測試一下:
#include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<thread> #include<map> #include<stack> #include<vector> #include<atomic> #include<Windows.h> #include<algorithm> using namespace std; class Unit { public : Unit() { this->num = 0; this->step = 0; this->numnum = 0; this->stepnum = 0; }; void ChangeStepNum() { step = step + 1; num = num + 1; //++step; //++num; } void ChangeStep() { step++; } void ChangeNum() { num++; } void GetAve() { if (this->num == this->step) cout << "Good" << endl; else cout << "Bad" << endl; } void PrintStepNum() { cout << "num" << this->num << endl; cout <<"step" << this->step << endl; } void equal() { if (this->num != this->step) cout << "???" << endl; } private : //atomic <int> step; //atomic <int> num; int step;//定義變數 int num;//讓這兩個變數同時改變 int stepnum; int numnum; }; void Change(Unit &unit)//同時改變兩個變數 { for (int i = 0; i < 10000; i++) { //unit.equal(); unit.ChangeNum(); unit.ChangeStep(); } unit.GetAve(); } int main() { Unit unit; thread t1(Change, ref(unit));//執行緒1 thread t2(Change, ref(unit));//執行緒2 t1.join(); t2.join(); unit.PrintStepNum(); Sleep(1000); for (int i = 0; i < 10000; i++) { unit.ChangeNum(); unit.ChangeStep(); } unit.PrintStepNum(); }
測試結果
我們可以看到,由於上邊闡述的原因 ,導致num和step一共改變了20000次但是最後結果卻不是20000,而且num!=step.
如果我們改成原子操作atomic,即atomic修飾的操作不可分割,未 修飾是num=num+1執行了三步:修飾之後變成了一步,變成了一個原子,不可分割。
atomic <int> step;
atomic <int> num;
//int step;//定義變數
//int num;//讓這兩個變數同時改變
測試結果
如果num== step就輸出good 否則輸出bad。
我們可以看到num是== step 的 而且 經過20000次++之後 ,確實加到了20000。
不過 還有一個問題,就是num和step是一起操作的,但是num和step一直都相等嗎。
應該不是的,對於AB兩個執行緒
void Change(Unit &unit)//同時改變兩個變數
{
for (int i = 0; i < 10000; i++)
{
//unit.equal();
unit.ChangeNum();
unit.ChangeStep();
}
unit.GetAve();
}
可能A執行緒剛執行到changenum時,B執行緒已經執行到changestep了,雖然我們給這兩個變數加了atomic。
此時我們在change之前加一個判斷函式,如果num!=step則問號警告。
測試一下:
可以得出,雖然最後num是==step的,但是在中間執行過程中並不是一直相等的。