Operacje na atomic-ach odzwierciedlają operacje sprzętowe i gwarantują, że zostaną wykonane w jednej transakcji (atomowo). CPU oferuje sporą liczbę mechanizmów, które są z nimi związane, z tego też względu standardowa biblioteka jest całkiem rozbudowana. Atomic-iem, może być każdy prymitywny typ (tylko takie obiekty mogą pojawić się w rejestrach CPU).
Przykłady:
// Dla std::atomic<int> x{0}; // Operacje: ++x; // atomowy pre-increment x++; // atomowy post-increment x += 1; // atomowy increment int y = x * 2; // atomowy odczyt x x = y + 2; // atomowy zapis do x // Uwaga, ta operacja jest niewspierana x *= 2; // ERROR // Atomowy odczyt x, po którym następuje atomowy zapis do x (dwie operacje) x = x * 2;W przykładzie poniżej, atomic posłużył do blokowania wątków, tak aby funkcje even/odd drukowały naprzemiennie tekst w momencie inkrementacji. Uwaga, nie ma gwarancji, że wartość counter wyświetlana na ekranie będzie zgodna z tym co było sprawdzane w if. Są to dwie atomowe operacje odczytu z pamięci, a wartość counter może się zmienić pomiędzy nimi.
#include <iostream> #include <thread> #include <atomic> using namespace std; std::atomic<int> counter{0}; void odd(size_t n) { for (size_t i = 0; i < n; i++) { if (counter % 2 == 1) { cout << "Odd increment: " << counter << endl; counter++; } else { cout << "Odd check: " << counter << endl; // wartość mogła się zmienić } std::this_thread::sleep_for(std::chrono::milliseconds{20}); } } void even(size_t n) { for (size_t i = 0; i < n; i++) { if (counter % 2 == 0) { cout << "Even increment: " << counter << endl; counter++; } else { cout << "Even check: " << counter << endl; // wartość mogła się zmienić } std::this_thread::sleep_for(std::chrono::milliseconds{40}); } } int main() { constexpr size_t steps{6}; std::thread t1{odd, steps}; std::thread t2{even, steps}; t1.join(); t2.join(); }Wynik:
Odd check: 0 Even increment: 0 Odd increment: 1 Even increment: 2 Odd increment: 3 Odd check: 4 Even increment: 4 Odd increment: 5 Odd check: 6 Even increment: 6 Even check: 7 Even check: 7
Brak komentarzy:
Prześlij komentarz