Я использую Cygwin GCC и запустить этот код:Почему код, изменяющий общую переменную через потоки, по-видимому, не страдает от состояния гонки?
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
unsigned u = 0;
void foo()
{
u++;
}
int main()
{
vector<thread> threads;
for(int i = 0; i < 1000; i++) {
threads.push_back (thread (foo));
}
for (auto& t : threads) t.join();
cout << u << endl;
return 0;
}
Составитель с линией: g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o
.
Он печатает 1000, что является правильным. Однако я ожидал меньшее число из-за того, что потоки перезаписывали ранее увеличиваемое значение. Почему этот код не страдает от взаимного доступа?
У моей тестовой машины 4 ядра, и я не накладываю никаких ограничений на программу, о которой я знаю.
Проблема сохраняется при замене содержимого общего foo
чем-то более сложным, например.
if (u % 3 == 0) {
u += 4;
} else {
u -= 1;
}
процессоров Intel имеет некоторую удивительную внутреннюю «сбить» логику, чтобы сохранить совместимость с очень ранними процессорами x86, используемыми в SMP-системах (например, с двумя процессорами Pentium Pro). Множество условий отказа, которые мы изучаем, практически никогда не происходит на машинах x86. Так сказать, ядро идет, чтобы написать 'u' обратно в память. ЦП действительно будет делать удивительные вещи, например, заметить, что строка памяти для 'u' не находится в кеше ЦП, и она перезапустит операцию увеличения. Вот почему переход от x86 к другим архитектурам может быть впечатляющим открытием! –
Возможно, все еще слишком быстро. Вам нужно добавить код, чтобы гарантировать, что поток выйдет до того, как он сделает что-нибудь, чтобы гарантировать, что другие потоки будут запущены до его завершения. –
Как уже упоминалось в другом месте, код потока настолько короток, что он может быть выполнен до того, как будет запущен следующий поток. Как насчет 10 потоков, которые помещают u ++ в цикл 100 циклов. И короткая задержка внутри до начала цикла (или глобальный флаг «go», чтобы запустить их все одновременно). – RufusVS