Używam Cygwin GCC i uruchamiam ten kod:
#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;
}
Zestawione z linii: g++ -Wall -fexceptions -g -std=c++14 -c main.cpp -o main.o
.
Drukuje 1000, co jest poprawne. Spodziewałem się jednak mniejszej liczby z powodu wątków nadpisujących poprzednio zwiększoną wartość. Dlaczego ten kod nie podlega wzajemnemu dostępowi?
Moja maszyna testowa ma 4 rdzenie i nie stawiam żadnych ograniczeń programowi, który znam.
Problem utrzymuje się przy zamianie treści udostępnionej na foo
coś bardziej złożonego np
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 lub 998 w moim systemie.
u
wraca do pamięci. Procesor faktycznie zrobi niesamowite rzeczy, na przykład zauważy, że linia pamięciu
nie znajduje się w pamięci podręcznej procesora i ponownie uruchomi operację inkrementacji. Dlatego przejście z x86 na inną architekturę może otworzyć oczy!