Wat is een race conditie?

Bij het schrijven van multi-threaded applicaties zijn "race conditions" een van de meest voorkomende problemen.

Mijn vragen aan de gemeenschap zijn:

Wat is een "race condition"? Hoe detecteer je ze? Hoe ga je ermee om? En tenslotte, hoe voorkom je dat ze zich voordoen?

Oplossing

Een "race condition" treedt op wanneer twee of meer threads toegang hebben tot gedeelde gegevens en ze proberen die tegelijkertijd te wijzigen. Omdat het thread scheduling algoritme op elk moment tussen threads kan wisselen, weet je niet in welke volgorde de threads zullen proberen toegang te krijgen tot de gedeelde gegevens. Daarom is het resultaat van de wijziging van de gegevens afhankelijk van het thread scheduling algoritme, d.w.z. beide threads zijn "racing" om de gegevens te openen/wijzigen.

Problemen ontstaan vaak wanneer een thread een "check-then-act" uitvoert (b.v. "check" of de waarde X is, dan "act" om iets te doen dat afhangt van het feit of de waarde X is) en een andere thread iets met de waarde doet tussen de "check" en de "act" in. Bv:

if (x == 5) // The "Check"
{
   y = x * 2; // The "Act"

   // If another thread changed x in between "if (x == 5)" and "y = x * 2" above,
   // y will not be equal to 10.
}

Het punt is, y kan 10 zijn, of het kan van alles zijn, afhankelijk van of een andere thread x veranderd heeft tussen de check en de act. Je hebt geen echte manier om dat te weten.

Om "race conditions" te voorkomen, zou je typisch een "lock" rond de gedeelde gegevens plaatsen, zodat slechts één thread tegelijk toegang heeft tot de gegevens. Dit zou ongeveer het volgende betekenen:

// Obtain lock for x
if (x == 5)
{
   y = x * 2; // Now, nothing can change x until the lock is released. 
              // Therefore y = 10
}
// release lock for x
Commentaren (18)

Een "race condition" is een soort bug, die alleen optreedt bij bepaalde temporele condities.

Voorbeeld: Stel je voor dat je twee threads hebt, A en B.

In Thread A:

if( object.a != 0 )
    object.avg = total / object.a

In Thread B:

object.a = 0

Als thread A wordt gepreempt net na te hebben gecontroleerd of object.a niet null is, zal B a = 0 doen, en als thread A de processor krijgt, zal het een "divide by zero" doen.

Deze bug gebeurt alleen als thread A wordt gepreempt net na het if statement, het'is zeer zeldzaam, maar het kan gebeuren.

Commentaren (0)

Een "race condition" is een situatie bij "concurrent programming" waarin twee gelijktijdige "threads" of processen wedijveren om een hulpbron en de resulterende "final state" afhangt van wie de hulpbron het eerst krijgt.

Commentaren (3)