Рассмотрим этот источник:
#include <string>
#include <iostream>
#include <thread>
using namespace std;
int *up;
void testf(){
for(int i = 0; i < 1000; i++)
for(int f = 0; f < 11; f++)
up[i]++;
}
int main() {
up = new int[1000];
std::thread tt[7];
for(int ts=0;ts<7;ts++) {
tt[ts]=std::thread(testf);
}
for(int ts=0;ts<7;ts++) {
tt[ts].join();
}
for(int i = 0; i < 1000; i++)
cout << up[i];
cout << endl;
delete[] up;
return 0;
}
Я намеренно записываю в тот же массив int без каких-либо мьютексов. Цикл for в testf()
будет увеличивать все элементы int up[1000]
на 11, и у нас есть 7 потоков. Таким образом, выход должен быть 77777777... (2000 Sevens)
Но иногда, когда я запускаю exe, я получаю патч чисел вроде этого:
...7777777066676672756866667777777777777377777366667777777...
Почему это происходит?
(для компиляции по linux: g++ -std = С++ 11 -pthread)
Причина в том, что "up [i] ++;" не является безопасным потоком. В основном это происходит:
С двумя потоками, что должно произойти:
Thread1 3) записать значение up [i] (4)
Thread2 1) прочитанное значение up [i] (4)
Что может случиться:
Thread2 1) прочитанное значение up [i] (3)
Thread1 2) добавьте один к считываемому значению (4)
Поэтому оба потока записывают 4 в массив!
Чтобы решить эту проблему, вам понадобится мьютекс или атомная операция приращения массива: http://baptiste-wicht.com/posts/2012/07/c11-concurrency-tutorial-part-4-atomic-type.html
std::thread
одновременно, поэтому вопрос вовсе не в безопасности потокаstd::thread
.