Próbuję zrozumieć wielowątkowość w c ++, ale utknąłem w tym problemie: jeśli uruchomię wątki w pętli for, wypiszą one nieprawidłowe wartości. To jest kod:
#include <iostream>
#include <list>
#include <thread>
void print_id(int id){
printf("Hello from thread %d\n", id);
}
int main() {
int n=5;
std::list<std::thread> threads={};
for(int i=0; i<n; i++ ){
threads.emplace_back(std::thread([&](){ print_id(i); }));
}
for(auto& t: threads){
t.join();
}
return 0;
}
Spodziewałem się wydrukowania wartości 0,1,2,3,4, ale często otrzymywałem tę samą wartość dwukrotnie. To jest wynik:
Hello from thread 2
Hello from thread 3
Hello from thread 3
Hello from thread 4
Hello from thread 5
Czego mi brakuje?
emplace_back
jest dziwne: emplace_back
bierze listę argumentów i przekazuje ją konstruktorowi std::thread
. Minąłeś instancję (rvalue) std::thread
, dlatego zbudujesz wątek, a następnie przeniesiesz ten wątek do wektora. Operację tę lepiej wyraża bardziej popularna metoda push_back
. Bardziej sensowne byłoby pisanie threads.emplace_back([i](){ print_id(i); });
(konstruowanie na miejscu) lub threads.push_back(std::thread([i](){ print_id(i); }));
(konstruowanie + ruch), które są nieco bardziej idiomatyczne.
i
przez wartość lambda,[i]
.