GNU/Linux >> Znalost Linux >  >> Linux

Spinlock versus Semafor

Spinlock a semafor se liší hlavně ve čtyřech věcech:

1. Jaké jsou
spinlock je jednou z možných implementací zámku, konkrétně takové, která je implementována rušným čekáním ("spinning"). Semafor je zobecnění zámku (nebo naopak zámek je speciální případ semaforu). Obvykle, ale ne nutně , spinlocky jsou platné pouze v rámci jednoho procesu, zatímco semafory lze použít i k synchronizaci mezi různými procesy.

Zámek funguje pro vzájemné vyloučení, tedy jeden vlákno najednou může získat zámek a pokračovat s "kritickou částí" kódu. Obvykle to znamená kód, který upravuje některá data sdílená několika vlákny.
semafor má počítadlo a nechá se získat jedním nebo několika vlákna, v závislosti na tom, jakou hodnotu do něj odešlete, a (v některých implementacích) v závislosti na tom, jaká je jeho maximální povolená hodnota.

Dosud lze zámek považovat za speciální případ semaforu s maximální hodnotou 1.

2. Co dělají
Jak bylo uvedeno výše, spinlock je zámek, a tedy mechanismus vzájemného vyloučení (přísně 1:1). Funguje tak, že se opakovaně dotazuje a/nebo upravuje umístění v paměti, obvykle atomickým způsobem. To znamená, že získání spinlocku je „zaneprázdněná“ operace, která možná spálí cykly CPU na dlouhou dobu (možná navždy!), zatímco efektivně nedosáhne „ničeho“.
Hlavní pobídkou pro takový přístup je skutečnost, že kontextový přepínač má režijní náklady ekvivalentní otočení několik set (nebo možná tisíc)krát, takže pokud lze zámek získat vypálením několika cyklů roztočení, může to být celkově velmi dobře. Efektivnější. Pro aplikace v reálném čase také nemusí být přijatelné blokovat a čekat, až se k nim plánovač vrátí v nějakém vzdáleném čase v budoucnu.

Naproti tomu semafor se buď neotáčí vůbec, nebo se točí jen velmi krátkou dobu (jako optimalizace, aby se zabránilo režii syscall). Pokud semafor nelze získat, zablokuje se a přenechá čas CPU jinému vláknu, které je připraveno ke spuštění. To může samozřejmě znamenat, že uplyne několik milisekund, než bude vaše vlákno znovu naplánováno, ale pokud to není žádný problém (obvykle není), pak to může být velmi efektivní, CPU-konzervativní přístup.

3. Jak se chovají v přítomnosti přetížení
Je běžnou mylnou představou, že spinlocky nebo algoritmy bez uzamčení jsou „obecně rychlejší“ nebo že jsou užitečné pouze pro „velmi krátké úlohy“ (v ideálním případě by žádný synchronizační objekt neměl být držen déle, než je nezbytně nutné).
Jediným důležitým rozdílem je, jak se různé přístupy chovají v přítomnosti přetížení .

Dobře navržený systém má obvykle nízké nebo žádné zahlcení (to znamená, že ne všechna vlákna se snaží získat zámek přesně ve stejnou dobu). Například za normálních okolností ne napsat kód, který získá zámek, poté načte půl megabajtu komprimovaných dat ze sítě, dekóduje a analyzuje data a nakonec upraví sdílenou referenci (připojí data do kontejneru atd.) před uvolněním zámku. Místo toho by člověk získal zámek pouze za účelem přístupu ke sdílenému zdroji .
Protože to znamená, že mimo kritickou sekci je podstatně více práce než uvnitř ní, je přirozeně pravděpodobnost, že vlákno bude uvnitř kritické sekce, relativně nízké, a proto o zámek současně bojuje jen málo vláken. Samozřejmě se tu a tam dvě vlákna pokusí získat zámek současně (pokud to nemohlo stalo se, že byste zámek nepotřebovali!), ale to je ve „zdravém“ systému spíše výjimka než pravidlo.

V takovém případě spinlock skvěle překonává semafor, protože pokud nedojde k přetížení zámku, režie na získání spinlocku je pouhý tucet cyklů ve srovnání se stovkami/tisíci cyklů pro přepnutí kontextu nebo 10-20 miliony cyklů pro ztrátu zbytku časového úseku.

Na druhou stranu, vzhledem k velkému přetížení nebo pokud je zámek držen po dlouhou dobu (někdy si prostě nemůžete pomoci!), spinlock spálí šílené množství cyklů CPU, aby ničeho nedosáhl.
Semafor (nebo mutex) je v tomto případě mnohem lepší volbou, protože umožňuje spuštění jiného vlákna užitečné úkoly během té doby. Nebo, pokud žádné jiné vlákno nemá něco užitečného na práci, umožňuje operačnímu systému snížit výkon procesoru a snížit teplo / šetřit energii.

Na jednojádrovém systému bude spinlock v přítomnosti zahlcení uzamčení také docela neefektivní, protože rotující vlákno bude ztrácet celý čas čekáním na změnu stavu, ke které nemůže dojít (ne, dokud nebude naplánováno uvolnění vlákna, což se neděje zatímco čekací vlákno běží!). Proto s ohledem na jakékoli množství sporů, získání zámku zabere v nejlepším případě asi 1 1/2 časových řezů (za předpokladu, že uvolnění vlákna je další naplánované), což není příliš dobré chování.

4. Jak jsou implementovány
Semafor v dnešní době obvykle zabalí sys_futex pod Linuxem (volitelně se spinlockem, který se po několika pokusech ukončí).
Spinlock je obvykle implementován pomocí atomických operací a bez použití čehokoli poskytovaného operačním systémem. V minulosti to znamenalo použití buď vnitřních prvků kompilátoru, nebo instrukcí nepřenosného assembleru. Mezitím jak C++11, tak C11 mají atomické operace jako součást jazyka, takže kromě obecné obtížnosti psaní prokazatelně správného kódu bez zámku je nyní možné implementovat kód bez zámku ve zcela přenosném a (téměř) bezbolestným způsobem.


Kromě toho, co řekli Yoav Aviram a gbjbaanb, bylo dalším klíčovým bodem to, že byste nikdy nepoužili spin-lock na stroji s jedním CPU, zatímco semafor by na takovém stroji dával smysl. V dnešní době je často těžké najít stroj bez více jader, hyperthreadingu nebo ekvivalentu, ale za okolností, kdy máte pouze jeden CPU, byste měli používat semafory. (Věřím, že důvod je zřejmý. Pokud je jeden CPU zaneprázdněn čekáním na něco jiného, ​​než uvolní spin-lock, ale běží na jediném CPU, je nepravděpodobné, že by zámek byl uvolněn, dokud nebude aktuální proces nebo vlákno preemptováno O/S, což může chvíli trvat a dokud nedojde k preempci, nestane se nic užitečného.)


velmi jednoduše, semafor je "výnosný" synchronizační objekt, spinlock je "busywait" objekt. (Semafory toho mají trochu víc v tom, že synchronizují několik vláken, na rozdíl od mutexu nebo ochrany nebo monitoru nebo kritické sekce, která chrání oblast kódu před jedním vláknem)

Semafor byste použili za více okolností, ale použijte spinlock tam, kde se zamykáte na velmi krátkou dobu – zamykání stojí náklady, zvláště pokud zamykáte hodně. V takových případech může být efektivnější chvíli spinlockovat a čekat, až se chráněný zdroj odemkne. Pokud točíte příliš dlouho, samozřejmě dojde ke snížení výkonu.

typicky pokud točíte déle než kvantum vláken, pak byste měli použít semafor.


Linux
  1. Ubuntu – Linux – Čas změny souboru versus čas úpravy?

  2. Jak zabít proces držení zámku Apt?

  3. Jak nastavit vlastní čas uzamčení obrazovky v Ubuntu 18.04?

  1. Stavy procesu Linuxu

  2. Jak obnovím semafor, když selže proces, který jej snížil na nulu?

  3. pthreads mutex vs semafor

  1. Rychlejší spouštění Linuxu

  2. Jaké unixové příkazy lze použít jako semafor/zámek?

  3. Časová synchronizace v heterogenním prostředí