Я использую 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;
}
while true; do res=$(./a.out); if [[ $res != 1000 ]]; then echo $res; break; fi; done;
вывода 999 или 998 в моей системе.
u
в память. ЦП на самом деле будет делать удивительные вещи, например, замечать, что строка памяти дляu
не находится в кеше ЦП, и перезапускает операцию увеличения. Вот почему переход от x86 к другим архитектурам может открыть глаза!