Race condition

V minulém díle jsem mluvil o tom, že procesor pomocí context switchingu přepíná mezi jednotlivými běžícími vlákny.

Otázka za 5 bludišťáků: lze přesně určit, které běžící vlákno doběhne dříve?

Odpověď: Prakticky nelze.

Je to dáno několika faktory:

  • První jednoduché procesory zpracovávaly instrukce napřímo, dnešní moderní procesory vykonávají jednotlivé instrukce v několika krocích v tzv. pipeline což se do češtiny překládá jako „roura“ ale takhle to říká málokdo, spíš člověk uslyší počeštěné „pipelajna“. V jednotlivých krocích pipelajny probíhají různé komplexní operace, včetně predikcí kdy se procesor snaží uhádnout výsledek instrukce (nebo následující instrukci) ještě před tím, než je instrukce spuštěna a to na základě krátkodobé statistiky, kterou si procesor ke spuštěným instrukcím udržuje. Délka této pipeliny je mezi 5 až 30 kroky. Vzhledem k prediktivním pipelajnám nelze odhadnout, jak daná instrukce proběhne rychle.
  • Context switching ovlivňují všechny možné faktory od typu operačního systému, aktuálního zatížení procesoru, počtu běžících procesů atd. apod.
  • Moderní procesory obsahují více jader, každé jádro obsahuje svoji vlastní pipelajnu.
  • Moderní procesory umí regulovat svoji frekvenci (pro ekonomický provoz) a umí to dokonce pouze pro konkrétní vlákna.
  • Různé instrukce trvají různě dlouho. Procesor má sice jednu danou frekvenci, např. 5 GhZ ale to neznamená, že procesor zvládne zpracovat 5 miliard instrukcí za vteřinu. Místo toho to znamená, že procesor zvládne 5 miliardů „ticků“ za vteřinu a různé instrukce procesoru mají různý počet ticků, za který se dokončí.

A nyní se dostáváme k tomu, co je Race condition – v češtině překládáno jako „souběh“ ale nikdy jsem neslyšel žádného ajťáka, který by tomu takhle říkal.

Race condition je jakákoliv situace, kdy se bez žádných dalších technik snažíte zjistit, které běžící vlákno ve vaší aplikaci doběhne dřív. V této situaci totiž můžete předpokládat, že je nepředvídatelné, které vlákno z libovolného počtu běžících vláken skončí jako první.

A to třeba i v případě, kdy v jednom vlákně spustíte instrukci „Počkej 100 vteřin“ a ve druhém vlákně spustíte instrukci „Počkej 1 vteřinu“.

Jasně, je celkem nepravděpodobné, že první vlákno doběhne dřív, než to druhé ale možné to je. V systému se může totiž stát například toto:

  • Spustíte vlákno A) „Počkej 1 vteřinu“
  • Spustíte vlákno B) „Počkej 100 vteřin“
  • Vlákno A) je přiřazené k jádru (X)
  • Vlákno B) je přiřazené k jádru (Y)
  • Jenže: ještě před přiřazeném vlákna A) k jádru (X) došlo nad tímto konkrétním jádrem ke spuštění nějakého výpočetně náročného vlákna z jiného procesu s vysokou prioritou a vzhledem k chybě programátora je jádro kompletně zahlceno. Vlákno A) s nižší prioritizací je kompletně vytěsněno.
  • Na jádru (Y) neprobíhají žádné náročné procesy a vlákno B) tak spokojeně běží a odpočítává 100 vteřin.
  • Za 100 vteřin skončí vlákno B).
  • Za 863 vteřin skončí zahlcení procesoru. Proces který zahlcoval jádro procesoru skončil.
  • Za 863.02 vteřin začne vlákno A)
  • Za 864.02 vteřin skončí vlákno A)

Jednoduchá poučka zní: pokud potřebujete při programování aplikací zjistit, které vlákno doběhne dřív, děláte něco špatně. Samozřejmě v programování existují techniky, ve kterých můžete vlákna synchronizovat takže třeba můžete v jednom vlákně říct, že v určitém bodě musí jedno vlákno počkat, dokud se něco nestane v druhém vlákně. O tom ale budu psát v jiné kapitole.

Pokud neprovádíte nějakou formu synchronizace, vlákna běží v nepředvídatelném čase a nelze určit, která instrukce ve kterém vlákně proběhne dřív.

Souhrn

  • Race condition je pojmenování situace, kdy se snažíte zjistit, které vlákno doběhne dřív.
  • Kdy které vlákno doběhne nelze (bez dalších technik jako např. synchronizace) předvídat.
  • Běžící vlákna lze různými způsoby synchronizovat ale bez této synchronizace nelze určit, která instrukce ve kterém vlákně proběhne dřív.
  • Běžící vlákna, která nejsou synchronizována, lze připodobnit k závodu formulí v mlze, který sledujete z tribuny na cílové čáře. Vidíte start a vidíte, kdo do cíle dojel dřív. Nemáte ale žádnou možnost jakkoliv ovlivnit, který z jezdců formule bude rychlejší, zkušenější a nebo který má lepší formuli.