C ++ Std Atomic

C ++ Std Atomic

Używamy „Atomic Std”, jeśli chcemy zachować atomowość operacji w C++. Atomowość to koncepcja, z którą możemy sobie poradzić, gdy pracujemy w operacjach/aplikacjach wielowy, w których nawet proste funkcje, takie jak czytanie i pisanie podczas wykonywania jednocześnie, mogą tworzyć problemy lub niezdefiniowane zachowania w kodzie. Aby poradzić sobie z taką sytuacją, C ++ zdefiniował bibliotekę „Std :: Atomic”, która gwarantuje spójność, która jest wystarczająco sekwencyjna do wykonywania czytania i pisania dla różnych odrębnych obiektów, które przedstawiają dobrze zdefiniowane zachowanie. Jeśli w pewnym momencie jeden wątek pisze, drugi wątek jest w tym czasie czytany.

Procedura:

W tym artykule zbadano, czym jest atomowość i jak możemy wykorzystać pojęcia Std Atomic, aby poradzić sobie z niezdefiniowanymi zachowaniami w naszych kodach. Omówimy różne funkcje Atomic STD i wdrożymy różne przykłady Atomic STD. Funkcja w ramach Atomic STD, którą zaimplementujemy w różnych przykładach, podano w następujący sposób:

  • Najprostsze czytanie i pisanie wartości
  • Uwolnij i pozyskaj zamówienie z pamięcią (model)
  • Model wymiany
  • Pobieranie operacji

Najprostsze czytanie i pisanie wartości

Utwórzmy aplikację wielowy w tym przykładzie, w którym tworzymy dwa wątki: jeden wątek do odczytu wartości i drugi wątek do zapisywania wartości. Za pomocą tego przykładu postaramy się uzyskać koncepcję atomiki STD, jakie są niezdefiniowane zachowania podczas uruchamiania zastosowań wielowymiarowych i w jaki sposób Atomia STD eliminuje niezdefiniowane zachowania.

W tym celu po prostu inicjujemy kod, przypisując dwie różne wartości do dwóch różnych zmiennych liczb całkowitych typu. Najpierw zainicjujemy zmienną „a” i „b” z typami danych liczb całkowitych. Następnie tworzymy funkcję zapisaną w pustce. W tej funkcji przypisujemy wartości zarówno do „a”, jak i „b”, e.G. Odpowiednio 25 i 20.

Następnie tworzymy funkcję odczytu. W funkcji odczytu wartości „a” i „b” są czytane za pomocą „std :: cout <

Wyjście:

Wyjście tego przykładu przedstawia niezdefiniowane zachowanie aplikacji, ponieważ wyjście kodu wynosi 0 lub 10. Stało się tak, ponieważ wątki wykonywały jednocześnie, a polecenie odczytu mogło zostać wykonane podczas wykonywania polecenia zapisu. W ten sposób otrzymaliśmy niekompletny wynik w wyjściu.

Atomia STD może rozwiązać ten problem i może sprawić, że niezdefiniowane zachowania w aplikacji są dobrze zdefiniowane. Aby to zaimplementować, po prostu dokonujemy niewielkiej zmiany podczas inicjowania i ustawiania wartości i typów danych zdefiniowanych zmiennych za pomocą „STD :: Atomic”. Definiujemy zmienną „A” i „B” jako zmienne atomowe według nazwy zmiennej „std :: Atomic zmiennej”. Dokonaliśmy również niewielkiej zmiany w funkcji zapisu, w której wcześniej przypisaliśmy wartości do A i B za pomocą operatora przypisania „=”. Ale tutaj przypisujemy wartości za pomocą „nazwy zmiennej. Metoda przechowywania (wartości) ”. Używamy „nazwy zmiennej. load () ”w funkcji odczytu. Reszta jest taka sama jak w poprzednim przykładzie.

Wartości w wyjściu są odczytywane i zapisywane w dobrze zdefiniowany sposób. A wielowytwórstwo jest również tutaj obsługiwane.

Uwolnij i pozyskaj zamówienie z pamięcią (model)

Model pamięci może mieć ogromny wpływ na funkcje odczytu i zapisu. Model pamięci jest funkcją domyślną, która zapewnia sekwencyjną spójność zamawiania. Jednym z najciekawszych modeli atomowych jest model wydania i pozyskania, w którym możemy przechowywać wydanie zamówienia pamięci dla pierwszego wątku oraz zamówienie pamięci uzyskane dla drugiego wątku, co oznacza, że ​​każdy sklep/zapis jest wykonany Najpierw w pierwszym wątku przed drugim wątkiem, ja.mi. obciążenie.

Tak więc, w przykładzie, możemy nawet zmienić jedną zmienną atomową „A” na nieatomową, a druga zmienna „B” jest przechowywana. W funkcji zapisu przechowujemy zmienną nieatomiczną „A”, po prostu przypisując jej dowolną wartość, e.G. 30. I prawidłowo przechowujemy wartość dla zmiennej atomowej „B” za pomocą „B. sklep (wartość, std :: pamięć_order_release) ”. To samo dotyczy funkcji odczytu, gdzie używamy „std :: cout <

Wyjście:

Atomowość operacji jest nadal utrzymywana z modelem uwalniania i nabytych pamięci, nawet gdy mieliśmy jedną nieatomową zmienną x. Stało się to z powodu Y (atomowe.magazyn), który upewnił się, że konserwacja sekwencyjnej spójności.

Model wymiany

Wymiana oznacza, gdy zamieniamy wartość zmiennej (atomowej) na inną wartość. W zamian wartość jest najpierw zamieniona, a następnie zwracana jest poprzednia wartość, która jest zamieniona. Po wymianie wartości odzwierciedla ona każdą kolejną operację tej wartości. Za pomocą przykładu wdrożymy tę wymianę zmiennych atomowych.

W tym przykładzie najpierw wprowadzamy globalny foobar zmiennej atomowej, który ma pewną wartość równą „15”. W głównym tworzeniu jednego wątku jako wątku1 i przypisujemy mu wartość całkowitą równą 2. Następnie, w pętli For, ustawiamy indeks od 0 do 100 razy. Następnie zastępujemy wartość zmiennej foobar na 2 za pomocą „foobar. wartość wymiany)". Następnie wychodzimy z pętli i ładujemy wartość zmiennej foobar, aby ją wydrukować. Po załadowaniu wartości foobar wymieniamy jego wartość na 18 przez „.Metoda wymiany (wartość do zastąpienia) ”. A następnie załaduj wartości Foobar i wyświetl je za pomocą metody drukowania.

Tutaj w tym przykładzie wątek musi wymieniać wartości na sto razy, a wartość Foobar jest wymieniana od 15 do 28. Każda operacja po tej wymianie zwraca tę samą wartość, jaką można zobaczyć na wyjściu.

Aportować

Fetch jest taki sam jak funkcja wymiany, która zapisuje wartości i zwraca wcześniej pobrane wartości. Ta operacja pobiera wartość, którą jest przechowywana przed nałożeniem do niej jakiejkolwiek operacji. Teraz w tym przykładzie implementujemy dodanie i pobieranie odejmowania. Zdefiniujemy zmienną atomową z typem danych niepodpisanym jako „liczba” i zainicjujemy liczbę z zero. Następnie tworzymy dwie funkcje - jedna dla Fetch Add i drugą dla odejmowania Fetch. Prowadzimy licznik przyrostu 1 dla dodania i zmniejszania 1 dla odejmowania w obu tych funkcjach. Następnie drukujemy te wartości zarówno z funkcji Fetch_Add, jak i Fetch_Sub w głównej.

Funkcja fetch_add zwróciła 0 i 1 jako poprzednie wartości przed przyrostem. Podobnie, fetch_sub zwrócił 2 i 1 jako wcześniej przechowywane wartości przed odejmowaniem lub zmniejszeniem jednego.

Wniosek

W tym artykule wdrożyliśmy podstawowe operacje w „STD :: Atomic”. Dowiedzieliśmy się, jak możemy poradzić sobie z problemami w aplikacjach wielowy za pomocą Atomic Std. Wdrożyliśmy różne przykłady w C ++ dla różnych funkcji, takich jak Fetch, Exchange, czytanie/pisanie i pamięć modelu Atomic Std, aby zapewnić sekwencyjną spójność i dobrze zdefiniowane zachowania kodu dla aplikacji wielowy.