我在 C 中創建了一個程式,當執行緒向量的組件使用 for 回圈創建時不起作用,并且在創建硬編碼時起作用。這是硬編碼示例:
std::vector<std::thread> ThreadVector;
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[0], 0);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[1],1);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[2],2);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[3],3);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[4],4);})));
for(auto& t:ThreadVector)
t.join();
maxLast是一個整數,它是雙字符陣列的值。該vals變數是一個特里普爾char陣列,認為在載體內的字串的向量。最后一個值是要通過函式發送的數字。cl.run 函式基本上只需要一個字符陣列陣列,將 maxLast 變數寫入檔案,然后在下一行寫入陣列中的下一個字串。呼叫檔案名,trying然后添加數字,然后.txt函式如下所示:
void dir::run(int nums, char *vals[nums], int count){
std::cout<<"got started "<<nums<<" "<<count<<std::endl;
std::string filestr = "trying" std::to_string(count) ".txt";
for(int i = 0; i < nums; i ){
writeLine(std::to_string(nums), filestr);
writeLine(std::string(vals[i]), filestr);
}
}
void dir::writeLine(std::string w, std::string p){
FILE* stream = fopen(p.c_str(), "a ");
fputs(w.c_str(), stream);
fputs("\n", stream);
fclose(stream);
}
當ThreadVector運行如上所示的硬編碼到變數中時,它運行良好。但是,如果我按照以下方式運行它,將會有一個名為的檔案trying5.txt,也會有我從未放入列印到檔案上的字符陣列中的字串。也會有一些執行緒收到相同的i值。
int i;
int ques=5;
for(i = 0; i < ques; i ){
printf("running %d\n", i);
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[i],i);})));
}
for(auto& t:ThreadVector)
t.join();
它列印到終端的運行之一上(清理了一下):
running 0
running 1
running 2
running 3
running 4
got started 30 2
got started 30 2
got started 30 4
got started 30 3
got started 30 4
這顯然不是應該發生的事情,正如前面提到的,有時終端會列印got started 30 5,我最終會得到一個名為trying5.txt. 我也試過push_back代替emplace_back.
uj5u.com熱心網友回復:
std::thread([&]
[&]意味著閉包捕獲的所有物件都被參考捕獲。
cl.run(maxLast, vals[i],i)
i被參考捕獲。i是父執行執行緒的回圈變數,它在回圈的每次迭代中遞增。
除非發生顯式同步,否則 C 無法保證每個執行執行緒何時執行與父執行執行緒中的任何內容相關的任何內容。
這里沒有發生這種同步。i在新的執行執行緒評估 thisval[i]以及i函式呼叫的離散引數時,父執行執行緒可能已經增加了;它已經結束了回圈的當前迭代并移動到下一個回圈。甚至多次迭代。或者回圈可能在父執行執行緒中完全結束,i現在處于其最終值。
got started 30 2
got started 30 2
got started 30 4
got started 30 3
got started 30 4
你可以在這里看到這個結果。每個執行執行緒i在父執行執行緒迭代和增加i不可預測的次數后開始對其進行評估。一些新的執行執行緒甚至設法同時進行評估i,導致 的觀察值相同i。
這就是“通過參考方式”捕獲物件的方法。用于按值[=]捕獲。這意味著每個執行執行緒在創建執行執行緒時看到每個捕獲物件的值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/391053.html
上一篇:“GIL”如何影響帶有i/o系結任務的Pythonasyncio`run_in_executor`?
下一篇:Python多處理一個類
