2009-07-07 20 views

Odpowiedz

98

nie. Jest używany jako zamiennik dla bardzo krótkotrwałych połączeń sennych.

Po wykonaniu wielowątkowego blokowania, jeśli zasób, który próbujesz uzyskać, jest już zablokowany, zwykle kładziesz się spać i czekasz, aż stanie się wolny. Gdy to zrobisz, zrezygnujesz z pozostałej części przydzielonej przez program planujący, aby użyć procesora, aby ktoś inny mógł go uruchomić. Zwykle jest to w porządku, szczególnie w przypadku długich okresów oczekiwania, takich jak oczekiwanie na IO, wiele innych procesów może działać na procesorze, gdy czekasz na obrót wrzeciona dysku.

Czasami jednak czekasz na malutką ilość czasu. W takich przypadkach normalnie zrezygnowałbyś z pozostałego czasu i czekał, aż wszystkie inne wątki zrobią swoje, zanim dostaniesz kolejną próbę. Możesz więc oszukać, zamiast czekać, siedzisz tam i ciągle odpytujesz "czy jesteśmy prawie jeszcze tam? droga. Jeśli blokada jest utrzymywana tylko przez ułamek pozostałego czasu, staje się bardzo skutecznym sposobem czekania, jest również bardzo skuteczna, ponieważ planista nie musi angażować się w reorganizację wszystkich innych wątków, aby użyć czasu, który podasz. jeśli czekałeś normalnie.

Oczywiście, jeśli kręcisz za każdym razem, gdy chcesz zablokować, nie będziesz zbyt popularny, Twoja aplikacja będzie leniwy i użyje 100% procesora, ale w bardzo małych dawkach, we właściwym czasie, robi to aplikacja jest bardziej responsywna.

Jeśli teraz zastanawiasz się, "kiedy powinienem go użyć?", To trudne wezwanie do zrobienia - jeśli masz zasób, który jest bardzo często zablokowany i odblokowany bardzo szybko, to spinlock wokół niego zamiast czekania to dobry pomysł (a następnie przetestuj swoją aplikację pod kątem wydajności), jeśli spróbujesz obracać się przez krótki czas, a następnie powrócisz do normalnego oczekiwania, to także rozsądny sposób. Ale generalnie nigdy nie będziesz musiał z niego korzystać.

+0

Powiedzmy, że chcemy średnio uzyskać 50ms opóźnienia, ile iteracji wykonujemy sprecyzować? –

+3

'SpinWait' rzadko spowoduje, że utkniesz przy 100% obciążeniu procesora, ponieważ zaczyna powodować powodowanie lub spadanie wątku, jeśli obraca się zbyt długo, w szczególności, jeśli liczba obrotów jest większa lub równa do 10, będzie "spać (1)" za każdy 19 obrót i "spać (0)" za każdy 4 obrót, i "wydajność" wtedy i tylko wtedy, gdy zostanie określone, że następny spin ma potencjał. lub "wydajność" w systemach wieloprocesorowych na dowolny punkt i nie trzeba czekać na początkowe 10 spinów. W systemie jednoprocesorowym "sleep" lub "yield" tylko "spać" ma wartość 10 lub niższą. –

+3

@ MichaelJ.Gray: Mylisz 'Thread.SpinWait()' (pytanie i odpowiedź) z 'var sw = new SpinWait(); sw.SpinOnce(); 'która wewnętrznie liczy się do 10 ... – DeepSpace101

70

Celem jest zrobienie "taniego" czekania, jeśli uważasz, że warunek, na który czekasz, spełni się bardzo, bardzo szybko. Zwykle, jeśli czekasz na coś, pozwalasz wątkowi przejść do trybu uśpienia, a procesor/system operacyjny przełączy się na inny wątek. Przełączniki kontekstu nie są szczególnie tanie, więc jeśli masz zaawansowaną wiedzę na temat sytuacji i uważasz, że taniej jest czekać niż na przełączanie kontekstu, możesz zacząć czekać.

Moja rada: jeśli chcesz zapytać, nie musisz jej używać. (Nigdy tego nie chciałem.) Zasadniczo jest to jedna z tych rzeczy, która jest naprawdę przydatna w niewielu sytuacjach, ale większość ludzi powinna pozostawać w spokoju.

+3

Zgaduję, że ten dotyczy całej kategorii "chyba, że ​​zmierzyłeś i znalazłeś problem ..." – jerryjvl

5

Jeśli chodzi o mnie (i jestem zadowolony z korekt!), Jedynym zastosowaniem oczekiwania wirowania jest zastosowanie mechanizmu blokowania lub mechanizmu inter-thread-callback. I nie powinny być wykonywane ręcznie (zwykle), ponieważ już istnieją.

Po zablokowaniu zasobu, a inny wątek żąda zsynchronizowanego dostępu do niego, zasadniczo musi poczekać na zakończenie pierwszego użycia tego wątku. To oczekiwanie można wykonać po prostu obracając się w pętli (lub inaczej przełączanie trybu spania i kontekstu, o czym wspomniał Jon).

+2

Jeden wyjątek - wewnątrz cyklu" Renderuj "(" Render() "silnika gry, aby ograniczyć liczbę klatek na sekundę. Żaden z pozostałych mechanizmów" Uśpij() "nie zapewnia wystarczającej gwarancji, kiedy zostanie ponownie włączony. – Basic

+2

@Basic Prawda, chociaż często się zdarza, że ​​pomija się okrążenia w cyklu renderowania, zamiast mieć wyraźną (zagnieżdżoną) pętlę oczekiwania Efekt jest taki sam, oczywiście –

14

Na marginesie, Microsoft pozbył się mechanizmu blokady spinów wątków z Windows 7, ponieważ nie skalował się dobrze dla wielordzeniowych procesorów. Spójrz na this:

+1

Mówi, że pozbyli się jednej blokady, której używają w Windows - spinlock dyspozytora. – Kevin