Spornost , také konkurence [ 1 ] , je chyba návrhu ve vícevláknovém systému nebo aplikaci, ve které provoz systému nebo aplikace závisí na pořadí, ve kterém jsou části kódu vykonávány. Chyba dostala svůj název podle podobné konstrukční chyby v elektronických obvodech (viz závodění signálů ).
Termín race condition odkazuje na inženýrský žargon a je výsledkem nedbalého doslovného překladu anglického ekvivalentu. V přísnějším akademickém prostředí je obvyklé používat termín nejistota souběžnosti .
Spor je „plovoucí“ chyba ( heisenbug ), která se objevuje v náhodných časech a „zmizí“, když se ji pokusíte lokalizovat.
Kvůli nekontrolovanému přístupu ke sdílené paměti může spor vést ke zcela odlišným chybám, které mohou nastat v nepředvídatelných časech, a pokus o replikaci chyby pro účely ladění s podobnými provozními podmínkami může selhat.
Hlavní důsledky mohou být:
Zařízení pro radiační terapii Therac-25 bylo prvním lékařským zařízením ve Spojených státech , které se z hlediska bezpečnosti spoléhalo pouze na software . Toto zařízení pracovalo ve třech režimech:
Tyto tři režimy nastavoval otočný disk, ve kterém byl otvor s vychylovacími magnety pro elektronickou terapii a terč s difuzorem pro rentgen. V důsledku závodního stavu mezi řídicím programem a motorem klávesnice se občas stalo, že v režimu RTG terapie byl disk v poloze „Elektronová terapie“ a pacient byl přímo ozářen elektronovým paprskem 25 MeV, který vedlo k přeexponování. Senzory zároveň zobrazovaly „Nulovou dávku“, takže operátor mohl postup zopakovat, což situaci ještě zhoršilo. V důsledku toho zemřeli nejméně dva pacienti.
Část kódu byla převzata z Therac-6 a Therac-20. Současně Therac-6 neměl rentgenovou terapii a Therac-20 měl hardwarová bezpečnostní opatření, která zabránila zapnutí záření, když byl disk ve špatné poloze.
Zvažte příklad kódu (v Javě ).
volatilní int x ; // Vlákno 1: while ( ! stop ) { x ++ ; … } // Vlákno 2: while ( ! stop ) { if ( x % 2 == 0 ) System . ven . println ( "x=" + x ); … }Nechť x=0. Předpokládejme, že se program spustí v následujícím pořadí:
Nejjednodušší způsob, jak to vyřešit, je zkopírovat proměnnou x do lokální proměnné. Zde je opravený kód:
// Vlákno 2: while ( ! stop ) { int cached_x = x ; if ( cached_x % 2 == 0 ) Systém . ven . println ( "x=" + cached_x ); … }Tato metoda přirozeně funguje pouze v případě, že existuje pouze jedna proměnná a kopírování se provádí v jedné strojové instrukci.
Složitější a „dražší“, ale také univerzálnější metodou řešení je synchronizace vláken , konkrétně:
int x ; // Vlákno 1: while ( ! stop ) { synchronized ( someObject ) { x ++ ; } … } // Vlákno 2: while ( ! stop ) { synchronizováno ( someObject ) { if ( x % 2 == 0 ) System . ven . println ( "x=" + x ); } … }Zde se děje předtím , než sémantika nevyžaduje klíčové slovo volatile.
Předpokládejme, že existují dvě proměnné (a klíčové slovo volatilenemá žádný vliv) a druhé vlákno System.out.printlnmá místo toho složitější zpracování. V tomto případě jsou obě metody neuspokojivé: první, protože jedna proměnná se může měnit, zatímco se druhá kopíruje; za druhé je synchronizováno příliš mnoho kódu.
Tyto metody lze kombinovat kopírováním „nebezpečných“ proměnných v synchronizovaném bloku. Na jednu stranu to odstraní omezení na jednu strojovou instrukci, na stranu druhou vám to umožní zbavit se příliš velkých synchronizačních bloků.
volatilní int x1 , x2 ; // Vlákno 1: while ( ! stop ) { synchronized ( someObject ) { x1 ++ ; x2 ++ ; } … } // Vlákno 2: while ( ! stop ) { int cached_x1 , cached_x2 ; synchronized ( someObject ) { cached_x1 = x1 ; cached_x2 = x2 ; } if (( cache_x1 + cache_x2 ) % 100 == 0 ) DoSomethingComplicated ( cached_x1 , cached_x2 ); … }Neexistují žádné zřejmé způsoby, jak zjistit a opravit podmínky závodu. Nejlepší způsob, jak se zbavit ras, je správně navrhnout multitaskingový systém.
Existuje třída chyb (a typy útoků, které je využívají), které umožňují neprivilegovanému programu ovlivňovat činnost jiných programů prostřednictvím schopnosti měnit veřejné zdroje (obvykle dočasné soubory ; soubor je k dispozici pro zápis všemi nebo částmi uživatelů systému v důsledku chyby programátora.
Útočící program může zničit obsah souboru a způsobit selhání programu oběti, nebo změnou dat donutit program provést nějakou akci na úrovni jeho oprávnění.
To je důvod, proč software s vážnými bezpečnostními požadavky, jako je webový prohlížeč , používá k pojmenování dočasných souborů náhodná čísla kryptografické kvality.