J'utilise Cygwin GCC et j'exécute ce code:
#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;
}
Compilé avec la ligne: g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o
.
Il imprime 1000, ce qui est correct. Cependant, je m'attendais à un nombre inférieur en raison de l'écrasement des threads sur une valeur précédemment incrémentée. Pourquoi ce code ne souffre-t-il pas d'un accès mutuel?
Ma machine de test a 4 cœurs, et je n'ai mis aucune restriction sur le programme que je connais.
Le problème persiste lors du remplacement du contenu du partagé foo
par quelque chose de plus complexe, par exemple
if (u % 3 == 0) {
u += 4;
} else {
u -= 1;
}
while true; do res=$(./a.out); if [[ $res != 1000 ]]; then echo $res; break; fi; done;
imprime 999 ou 998 sur mon système.
u
en mémoire. Le CPU fera en fait des choses étonnantes comme remarquer que la ligne de mémoire pouru
n'est pas dans le cache du CPU et il redémarrera l'opération d'incrémentation. C'est pourquoi passer de x86 à d'autres architectures peut être une expérience révélatrice!