C Language
Atomics
Szukaj…
Składnia
-
#ifdef __STDC_NO_ATOMICS__
-
# error this implementation needs atomics
-
#endif
-
#include <stdatomic.h>
- unsigned _Atomic counter = ATOMIC_VAR_INIT (0);
Uwagi
Atomics jako część języka C to opcjonalna funkcja dostępna od wersji C11.
Ich celem jest zapewnienie bez wyścigu dostępu do zmiennych, które są współużytkowane przez różne wątki. Bez kwalifikacji atomowej stan zmiennej dzielonej byłby niezdefiniowany, gdyby dwa wątki miały do niej dostęp jednocześnie. Np. Operację przyrostową ( ++
) można podzielić na kilka instrukcji asemblera, odczyt, sam dodatek i instrukcję przechowywania. Jeśli inny wątek wykonałby tę samą operację, ich dwie sekwencje instrukcji mogłyby zostać splecione i doprowadzić do niespójnego wyniku.
Typy: Wszystkie typy obiektów z wyjątkiem typów tablic można zakwalifikować za pomocą
_Atomic
.Operatory: Wszystkie operatory odczytu-modyfikacji-zapisu (np.
++
lub*=
) na nich mają charakter atomowy.Operacje: Istnieje kilka innych operacji, które są określone jako funkcje ogólne typu, np.
atomic_compare_exchange
.Wątki: Dostęp do nich jest gwarantowany, aby nie generować wyścigu danych, gdy są dostępne dla różnych wątków.
Procedury obsługi sygnałów: typy atomowe nazywane są bez blokady, jeśli wszystkie operacje na nich są bezstanowe. W takim przypadku można ich również użyć do zmiany stanu między normalnym przepływem sterowania a obsługą sygnału.
Istnieje tylko jeden typ danych, który gwarantuje brak blokady:
atomic_flag
. Jest to minimalny typ, którego operacje mają na celu mapowanie do wydajnych instrukcji testowania i ustawiania sprzętu.
Inne sposoby uniknięcia warunków wyścigu są dostępne w interfejsie wątków C11, w szczególności typ mutex mtx_t
aby wzajemnie wykluczać wątki z dostępu do krytycznych danych lub krytycznych sekcji kodu. Jeśli atomics nie są dostępne, należy ich użyć, aby zapobiec wyścigom.
atomika i operatory
Dostęp do zmiennych atomowych można uzyskać jednocześnie między różnymi wątkami bez tworzenia warunków wyścigu.
/* a global static variable that is visible by all threads */
static unsigned _Atomic active = ATOMIC_VAR_INIT(0);
int myThread(void* a) {
++active; // increment active race free
// do something
--active; // decrement active race free
return 0;
}
Wszystkie operacje wartości (operacje modyfikujące obiekt), które są dozwolone dla typu podstawowego są dozwolone i nie doprowadzą do warunków wyścigu między różnymi wątkami, które mają do nich dostęp.
- Operacje na obiektach atomowych są zwykle o rząd wielkości wolniejsze niż normalne operacje arytmetyczne. Obejmuje to również proste operacje ładowania lub przechowywania. Dlatego powinieneś ich używać tylko do krytycznych zadań.
- Zwykłe operacje arytmetyczne i przypisanie, takie jak
a = a+1;
w rzeczywistości są trzy operacje na : pierwszy ładunek, a następnie dodawanie i wreszcie sklep.a
To nie jest wolne od wyścigów. Tylko operacjaa += 1;
ia++;
są.