Odpowiedzi:
Kiedy używasz zwykłych blokad (muteksy, sekcje krytyczne itp.), System operacyjny ustawia twój wątek w stan OCZEKIWANIA i wywłaszcza go, planując inne wątki w tym samym rdzeniu. Ma to spadek wydajności, jeśli czas oczekiwania jest naprawdę krótki, ponieważ twój wątek musi teraz czekać na wywłaszczanie, aby ponownie otrzymać czas procesora.
Poza tym obiekty jądra nie są dostępne w każdym stanie jądra, na przykład w obsłudze przerwań lub gdy stronicowanie nie jest dostępne itp.
Spinlocki nie powodują wywłaszczania, ale czekają w pętli („spin”), aż drugi rdzeń zwolni blokadę. Zapobiega to utracie kwantu wątku i kontynuowaniu działania, gdy tylko blokada zostanie zwolniona. Prosty mechanizm spinlocków pozwala jądru wykorzystać go w prawie każdym stanie.
Dlatego na komputerze z jednym rdzeniem blokada spinlock jest po prostu „wyłączaniem przerwań” lub „podnoszeniem IRQL”, co całkowicie uniemożliwia planowanie wątków.
Spinlocky ostatecznie pozwalają jądrom uniknąć "Big Kernel Lock" (blokada uzyskiwana, gdy rdzeń wchodzi do jądra i zwalniana przy wyjściu) i mają granularne blokowanie nad prymitywami jądra, powodując lepsze przetwarzanie wielordzeniowe na maszynach wielordzeniowych, a tym samym lepszą wydajność.
EDYCJA : Pojawiło się pytanie: „Czy to oznacza, że powinienem używać spinlocków wszędzie tam, gdzie to możliwe?” i spróbuję odpowiedzieć:
Jak wspomniałem, spinlocki są przydatne tylko w miejscach, w których przewidywany czas oczekiwania jest krótszy niż kwant (czytaj: milisekundy), a wywłaszczanie nie ma większego sensu (np. Obiekty jądra nie są dostępne).
Jeśli czas oczekiwania jest nieznany lub jeśli jesteś w trybie użytkownika, Spinlocki nie są wydajne. Zużywasz 100% czasu procesora na oczekującym rdzeniu podczas sprawdzania, czy blokada jest dostępna. Zapobiegasz uruchamianiu innych wątków na tym rdzeniu, dopóki kwant nie wygaśnie. Ten scenariusz jest możliwy tylko w przypadku krótkich serii na poziomie jądra i mało prawdopodobna opcja dla aplikacji w trybie użytkownika.
Oto pytanie dotyczące SO, które dotyczy tego: Spinlocks, jak przydatne są?
Powiedzmy, że zasób jest chroniony przez blokadę, a wątek, który chce uzyskać dostęp do zasobu, musi najpierw uzyskać blokadę. Jeśli blokada nie jest dostępna, wątek może wielokrotnie sprawdzać, czy blokada została zwolniona. W tym czasie zajęty wątek czeka, sprawdzając blokadę, używając procesora, ale nie wykonując żadnej użytecznej pracy. Taka blokada jest określana jako blokada spinowa.
Jest to istotna pętla, która trwa, dopóki nie zostanie spełniony określony warunek:
while(cantGoOn) {};
sleep(0)
, spowoduje to wywłaszczenie wątku, zabijając cel używania spinlocka w pierwszej kolejności. jeśli chcesz poddać się innym wątkom, powinieneś używać zwykłej blokady. (Wiem, że twój komentarz jest bardzo stary, ale chciałem, aby inni nie postrzegali go jako sugestii).
while(something != TRUE ){};
// it happend
move_on();
To rodzaj zamka, który jest zajęty czekaniem
Jest to uważane za anty-wzorzec, z wyjątkiem programowania sterowników bardzo niskiego poziomu (gdzie może się zdarzyć, że wywołanie „właściwej” funkcji oczekiwania wiąże się z większym narzutem niż zwykłe blokowanie na kilka cykli).
Zobacz na przykład Spinlocks w jądrze Linuksa .
SpinLocks to te, w których wątek czeka, aż blokada będzie dostępna. Zwykle jest to używane, aby uniknąć narzutu związanego z pobieraniem obiektów jądra, gdy istnieje zakres uzyskania obiektu jądra w jakimś krótkim okresie czasu.
Dawny:
While(SpinCount-- && Kernel Object is not free)
{}
try acquiring Kernel object
Chciałbyś użyć spinlocka, gdy uważasz, że tańsze jest wejście do zajętej pętli oczekiwania i połączenie zasobu zamiast blokowania, gdy zasób jest zablokowany.
Obracanie może być korzystne, gdy zamki są drobnoziarniste i duże (na przykład blokada na węzeł w połączonej liście), a także gdy czasy utrzymania blokad są zawsze bardzo krótkie. Generalnie, trzymając blokadę spinu, należy unikać blokowania, wywoływania czegokolwiek, co samo może blokować, trzymania więcej niż jednej blokady spinu naraz, wykonywania wywołań wysyłanych dynamicznie (interfejs i wirtualne), wykonywania wywołań wysyłanych statycznie do dowolnego kodu, którego się nie robi. posiadanie lub przydzielanie pamięci.
Należy również zauważyć, że SpinLock jest typem wartości ze względu na wydajność. W związku z tym należy bardzo uważać, aby przypadkowo nie skopiować instancji SpinLock, ponieważ dwie instancje (oryginał i kopia) byłyby wówczas całkowicie niezależne od siebie, co prawdopodobnie doprowadziłoby do błędnego zachowania aplikacji. Jeśli instancja SpinLock musi być przekazywana, powinna być przekazywana przez odwołanie, a nie przez wartość.
W skrócie, spinlock wykorzystuje atomowe porównywanie i zamianę (CAS) lub testowanie i ustawianie, takie jak instrukcje, aby zaimplementować idiom lock free, wait free thread safe. Takie struktury dobrze skalują się w maszynach wielordzeniowych.
Cóż, tak - celem blokad spinu (w porównaniu z tradycyjnymi krytycznymi sekcjami itp.) Jest to, że oferują one lepszą wydajność w pewnych okolicznościach (systemy wielordzeniowe ...), ponieważ nie dają od razu pozostałej części kwantowej wątku.
Spinlock to rodzaj zamka, który nie jest w stanie blokować ani spać. Każdy wątek, który chce uzyskać blokadę spinlock dla dowolnego udostępnionego lub krytycznego zasobu, będzie stale obracał się, marnując cykl przetwarzania procesora, aż uzyska blokadę dla określonego zasobu. Po zdobyciu spinlocka, próbuje zakończyć pracę w swoim kwantie, a następnie odpowiednio zwolnić zasób. Spinlock jest rodzajem zamka o najwyższym priorytecie, można po prostu powiedzieć, że jest to blokada bez wywłaszczania.