Какво е състояние на състезание?

При писането на многонишкови приложения един от най-често срещаните проблеми са състезателните състояния.

Въпросите ми към общността са:

Какво е състояние на надпревара? Как ги откривате? Как се справяте с тях? И накрая, как предотвратявате появата им?

Решение

Състезателно състояние възниква, когато две или повече нишки имат достъп до споделени данни и се опитват да ги променят едновременно. Тъй като алгоритъмът за планиране на нишки може да се разменя между тях по всяко време, вие не знаете реда, в който нишките ще се опитат да получат достъп до споделените данни. Следователно резултатът от промяната на данните зависи от алгоритъма за планиране на нишките, т.е. и двете нишки се "състезават" за достъп/промяна на данните.

Често възникват проблеми, когато една нишка прави "проверка, след това действие" (например "проверка" дали стойността е X, след това "действие", за да направи нещо, което зависи от това дали стойността е X), а друга нишка прави нещо със стойността между "проверката" и "действието". Напр:

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.
}

Смисълът е, че y може да е 10 или да е нещо друго, в зависимост от това дали друга нишка е променила x между проверката и действието. Вие нямате реален начин да знаете.

За да предотвратите появата на състезателни условия, обикновено поставяте заключване около споделените данни, за да гарантирате, че само една нишка може да има достъп до данните в даден момент. Това би означавало нещо подобно:

// 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
Коментари (18)

Състезателното условие е вид грешка, която се проявява само при определени времеви условия.

Пример: Представете си, че имате две нишки, A и B.

В нишка А:

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

В нишка B:

object.a = 0

Ако нишката A бъде изпреварена точно след като е проверила, че object.a не е null, B ще направи a = 0, а когато нишката A получи процесора, ще направи "деление на нула".

Този бъг се случва само когато нишката А е изпреварена точно след if оператора, това се случва много рядко, но може да се случи.

Коментари (0)

Състезателно условие е ситуация в паралелното програмиране, при която две паралелни нишки или процеси се конкурират за ресурс и крайното състояние зависи от това кой първи ще получи ресурса.

Коментари (3)