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