2008-10-16 14 views
19

Natknąłem się na funkcję InterlockedExchange i zastanawiałem się, kiedy powinienem użyć tej funkcji. Moim zdaniem, ustawienie wartości 32-bitowej na procesorze x86 powinno zawsze być atomowe?
W przypadku, gdy chcę korzystać z funkcji, nowa wartość nie zależy od starej wartości (nie jest to operacja przyrostu). można podać przykład, w którym metoda ta jest obowiązkowa (ja nie szukam InterlockedCompareExchange)Kiedy należy używać funkcji Win32 InterlockedExchange?

Odpowiedz

4

W maszynie wieloprocesorowej lub wielordzeniowej każdy rdzeń ma własną pamięć podręczną - tak każdy rdzeń ma każdy potencjalnie inny "widok" zawartości pamięci systemowej.

mechanizmy synchronizacji wątku dbać o synchronizacji pomiędzy rdzeniami, aby uzyskać więcej informacji znajdziesz na http://blogs.msdn.com/oldnewthing/archive/2008/10/03/8969397.aspx lub google dla nabywać i zwolnij semantykę

+2

Pamięć podręczna jest tutaj pomocnicza. Nawet jeśli nie ma pamięci podręcznych i procesory rozmawiają z pamięcią, normalna sekwencja odczytu/zapisu nie jest atomowa. – Suma

10

InterlockedExchange jest zarówno zapis i odczytu - zwraca poprzednią wartość.

Jest to konieczne, aby kolejny wątek nie zapisał innej wartości zaraz po tym. Załóżmy na przykład, że próbujesz zwiększyć zmienną. Możesz odczytać wartość, dodać 1, a następnie ustawić nową wartość za pomocą InterlockedExchange. Wartość zwrócona przez InterlockedExchange musi być zgodna z pierwotnie odczytaną wartością, w przeciwnym razie inny wątek prawdopodobnie zwiększyłby ją w tym samym czasie, a następnie musisz wykonać pętlę i spróbować ponownie.

+3

W tym przypadku użyłbym InterlockedCompareExchange, ponieważ sprawdzenie, czy wartość była nadal oryginalna, odbywa się już za pomocą metody. – EFrank

+3

Lub po prostu InterlockedIncrement –

11

Oprócz wpisywania nowej wartości, InterlockedExchange również odczytuje i zwraca poprzednią wartość; cała ta operacja jest atomowa. Jest to przydatne dla lock-free algorithms.

(Nawiasem mówiąc, pisze 32-bitowe nie są gwarancją atomowy. Rozważmy przypadek, gdy zapis jest niewyrównany i okrakiem granicę cache, na przykład.)

+0

Byłby atomowy z punktu widzenia oprogramowania działającego na procesorze, ale nie z punktu widzenia sprzętu siedzącego w autobusie. –

+1

Czy byłby atomowy z POV oprogramowania działającego na innym rdzeniu? A co z napisem, który okala granicę strony i uruchamia błąd? Minęły lata, odkąd zrobiłem kodowanie x86 na niskim poziomie, zgaduję, że mogę kłamać:/ – moonshadow

3

Ustawienie wartość 32-bitowa jest atomowa, ale tylko jeśli ustawiasz literał.

B = A oznacza 2 operacje:

mov   eax,dword ptr [a] 
mov   dword ptr [b],eax 

Teoretycznie nie może być pewne przerwy pomiędzy pierwszą i druga operacja.

+4

A gdyby wystąpiła jakaś przerwa, to co - potrwa to trochę dłużej, ale wartość eax się nie zmieni. Prawdziwym punktem InterlockedExchange jest to, że jest to atomowy odczyt i zapis. – Suma

+1

Co następnie? Piekło. Przerwanie może spowodować wywołanie systemowe, system wywołuje przełącznik kontekstowy, a następnie inny wątek zmienia wartość. Następnie EAX zostaje przywrócony, a wartość zostaje ponownie zmieniona. Warunki wyścigu są szczególnie śmiertelne podczas liczenia odniesień. Niektóre wątki mogą zwiększać wartość, podczas gdy inny wątek zmniejsza wartość lub dwa wątki mogą ją zwiększać w tym samym czasie. Przywrócenie EAX nie jest rozwiązaniem - jest to problem. –

+0

I jeszcze gorzej, gdy jest więcej niż jeden procesor/rdzeń. – SamB

3

Pisanie wartość nigdy nie jest atomowy domyślnie. Kiedy piszesz wartość do zmiennej, generowanych jest kilka instrukcji maszynowych. Dzięki nowoczesnym, prewencyjnym systemom operacyjnym, system operacyjny może przełączyć się na inny wątek pomiędzy poszczególnymi operacjami zapisu.

Jest to jeszcze większy problem na maszynach wieloprocesorowych, w których może być wykonywanych jednocześnie kilka wątków i próbujących jednocześnie pisać w jednym miejscu w pamięci.

Zablokowane operacje unikają tego, używając wyspecjalizowanych instrukcji do zapisu (x86 ma dedykowane instrukcje dla tego rodzaju sytuacji), które wykonują read-modyfikuj-pisz w jednej instrukcji. Te instrukcje blokują również magistralę pamięci wszystkich procesorów, aby upewnić się, że żaden inny wątek wykonawczy nie może zapisywać wartości w tym samym czasie.

+0

-1, Niepoprawne zapisy z wyrównanym wyrównaniem są atomami na x86. – Johan

2

InterlockedExchange dba o to, aby zmiana zmiennej i powrót jej pierwotnej wartości nie zostały przerwane przez inne wątki.

Tak więc, jeśli „Ja” jest int, te rozmowy (podejmowane indywidualnie) nie muszą InterlockedExchange wokół „i”:

a = i; 
i = 9; 
i = a; 
i = a + 9; 
a = i + 9; 
if(0 == i) 

Żadne z tych stwierdzeń polegać zarówno na początkowych i końcowych wartości " ja'. Ale te następujące połączenia NIE trzeba InterlockedExchange wokół „i”:

a = i++; //a = InterlockedExchange(&i, i + 1); 

Bez niej dwa wątki uruchomione przez ten sam kod może uzyskać taką samą wartość „i” przydzielony do „A” lub „a” może nieoczekiwanie pominąć dwie lub więcej liczb.

if(0 == i++) //if(0 == InterlockedExchange(&i, i + 1)) 

Dwa wątki mogą wykonywać kod, który ma się wydarzyć tylko raz.
itp.

+0

Niewłaściwy przykład 'a = InterlockedExchange (& i, i + 1);'.Twoje 'i' może być zmienione przez inne CPU pomiędzy' i + 1' i 'InterlockedExchange'. – Fr0sT

-1

wow, tyle sprzecznych odpowiedzi. Trudno przesądzać, kto ma rację, kto jest zły, a jakie informacje wprowadzają w błąd.

jestem pewny odpowiedź też, biorąc pod uwagę powyższe pół-odpowiedzi, ale myślę, że to działa w ten sposób, może się mylę, i to będzie interesujące, aby dowiedzieć się, czy jestem:

  1. 32-bitowy odczyt & pisze SĄ atomowe, ale w zależności od kodu, może to nie oznaczać wiele.
  2. Nie przejmuj się brakiem wyrównania odczytu/zapisu. WSZYSTKIE 32-bitowe zapisy do 32-bitowej zmiennej muszą być wyrównane lub błędy strony maszynowej.
  3. nie martw się o zawijanie tekstu wokół strony podręcznej, co nie może się zdarzyć.
  4. Jeśli musisz pisać i czytać w jednym wątku, a piszesz na innym wątku, musisz użyć InterlockedExchange. Jeśli po prostu czytasz wartość w jednym wątku i zapisujesz ją na innym, to nie musisz jej używać, ale te wartości mogą być niestabilne z powodu wielowątkowości.
+0

-1 32-bitowe partie nie muszą być wyrównane na x86. A 32-bitowe zapisy są atomiczne na x86, ale nie na wielu innych architekturach. – Johan

Powiązane problemy