Ich verwende Cygwin GCC und führe diesen Code aus:
#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;
}
Zusammengestellt mit der Zeile : g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o
.
Es werden 1000 gedruckt, was korrekt ist. Ich habe jedoch eine geringere Anzahl erwartet, da Threads einen zuvor inkrementierten Wert überschreiben. Warum leidet dieser Code nicht unter gegenseitigem Zugriff?
Mein Testgerät hat 4 Kerne und ich habe dem mir bekannten Programm keine Einschränkungen auferlegt.
Das Problem besteht weiterhin, wenn der Inhalt des freigegebenen foo
durch etwas Komplexeres ersetzt wird, z
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 oder 998 auf meinem System drucken.
u
in den Speicher zurückgeschrieben. Die CPU wird tatsächlich erstaunliche Dinge tun, z. B. feststellen, dass sich die Speicherzeile füru
nicht im Cache der CPU befindet, und den Inkrementierungsvorgang neu starten. Aus diesem Grund kann der Wechsel von x86 zu anderen Architekturen eine Erfahrung sein, die die Augen öffnet!