Состояние гонки

Поделись знанием:
Перейти к: навигация, поиск

Состоя́ние го́нки (англ. race condition) — ошибка проектирования многопоточной системы или приложения, при которой работа системы или приложения зависит от того, в каком порядке выполняются части кода. Своё название ошибка получила от похожей ошибки проектирования электронных схем (см. Гонки сигналов).

Состояние гонки — «плавающая» ошибка (гейзенбаг), проявляющаяся в случайные моменты времени и «пропадающая» при попытке её локализовать.





Пример

Рассмотрим пример кода (на Java).

volatile int x;
// Поток 1:
while (!stop)
{
  x++;
  …
}
// Поток 2:
while (!stop)
{
  if (x%2 == 0)
    System.out.println("x=" + x);
  …
}

Пусть x=0. Предположим, что выполнение программы происходит в таком порядке:

  1. Оператор if в потоке 2 проверяет x на чётность.
  2. Оператор «x++» в потоке 1 увеличивает x на единицу.
  3. Оператор вывода в потоке 2 выводит «x=1», хотя, казалось бы, переменная проверена на чётность.

Способы решения

Локальная копия

Самый простой способ решения — копирование переменной x в локальную переменную. Вот исправленный код:

// Поток 2:
while (!stop)
{
  int cached_x = x;
  if (cached_x%2 == 0)
    System.out.println("x=" + cached_x);
  …
}

Естественно, этот способ работает только тогда, когда переменная одна и копирование производится за одну машинную команду.

Синхронизация

Более сложный, но и более универсальный метод решения — синхронизация потоков, а именно:

int x;
// Поток 1:
while (!stop)
{
  synchronized(SomeObject)
  {
    x++;
  }
  …
}
// Поток 2:
while (!stop)
{
  synchronized(SomeObject)
  {
    if (x%2 == 0)
      System.out.println("x=" + x);
  }
  …
}

Здесь семантика happens before не требует ключевое слово volatile.

Комбинированный способ

Предположим, что переменных — две (и ключевое слово volatile не действует), а во втором потоке вместо System.out.println стоит более сложная обработка. В этом случае оба метода неудовлетворительны: первый — потому что одна переменная может измениться, пока копируется другая; второй — потому что засинхронизирован слишком большой объём кода.

Эти способы можно скомбинировать, копируя «опасные» переменные в синхронизированном блоке. С одной стороны, это снимет ограничение на одну машинную команду, с другой — позволит избавиться от слишком больших синхроблоков.

volatile int x1, x2;
// Поток 1:
while (!stop)
{
  synchronized(SomeObject)
  {
    x1++;
    x2++;
  }
  …
}
// Поток 2:
while (!stop)
{
  int cached_x1, cached_x2;
  synchronized (SomeObject)
  {
    cached_x1 = x1;
    cached_x2 = x2;
  }
  if ((cached_x1 + cached_x2)%100 == 0)
    DoSomethingComplicated(cached_x1, cached_x2);
  …
}

Очевидных способов выявления и исправления состояний гонки не существует. Лучший способ избавиться от гонок — правильное проектирование многозадачной системы.

Случай с Therac-25

Аппарат лучевой терапии Therac-25 был первым в США медицинским аппаратом, в котором вопросы безопасности были возложены исключительно на программное обеспечение. Этот аппарат работал в трёх режимах:

  1. Электронная терапия: электронная пушка напрямую облучает пациента; компьютер задаёт энергию электронов от 5 до 25 МэВ.
  2. Рентгеновская терапия: электронная пушка облучает вольфрамовую мишень, и пациент облучается рентгеновскими лучами, проходящими через конусообразный рассеиватель. В этом режиме энергия электронов постоянна: 25 МэВ.
  3. В третьем режиме никакого излучения не было. На пути электронов (на случай аварии) располагается стальной отражатель, а излучение имитируется светом. Этот режим применяется для того, чтобы точно навести пучок на больное место.

Эти три режима задавались вращающимся диском, в котором было отверстие с отклоняющими магнитами для электронной терапии, и мишень с рассеивателем для рентгеновской. Из-за состояния гонки между управляющей программой и обработчиком клавиатуры иногда случалось, что в режиме рентгеновской терапии диск оказывался в положении «Электронная терапия», и пациент напрямую облучался пучком электронов в 25 МэВ, что вело к переоблучению. При этом датчики выводили «Нулевая доза», поэтому оператор мог повторить процедуру, усугубляя ситуацию. В результате погибли как минимум четыре пациента.

Часть кода была взята из Therac-6 и Therac-20. При этом в Therac-6 не было рентгеновской терапии, а в Therac-20 были аппаратные меры безопасности, которые не давали включить излучение, когда диск был в неправильном положении.

Взломы путём эксплуатирования состояния гонки

Существует класс ошибок (и эксплуатирующих их типов атак), позволяющих непривилегированной программе влиять на работу других программ через возможность изменения общедоступных ресурсов (обычно — вре́менных файлов; англ. /tmp race — состояние гонки во вре́менном каталоге), в определённое временно́е окно, в которое файл по ошибке программиста доступен для записи всем или части пользователей системы.

Атакующая программа может разрушить содержимое файла, вызвав аварийное завершение программы-жертвы, или, подменив данные, заставить программу выполнить какое-либо действие на уровне своих привилегий.

Именно по этой причине ПО с серьёзными требованиями по безопасности, такое, как веб-браузер, использует случайные числа криптографического качества для именования временных файлов.

Напишите отзыв о статье "Состояние гонки"

Примечания

См. также


К:Википедия:Статьи без источников (тип: не указан)

Отрывок, характеризующий Состояние гонки

– Правда, что Наташа еще молода, но так долго.
– Это не могло быть иначе, – со вздохом сказал князь Андрей.
– Я пошлю вам ее, – сказала графиня и вышла из комнаты.
– Господи, помилуй нас, – твердила она, отыскивая дочь. Соня сказала, что Наташа в спальне. Наташа сидела на своей кровати, бледная, с сухими глазами, смотрела на образа и, быстро крестясь, шептала что то. Увидав мать, она вскочила и бросилась к ней.
– Что? Мама?… Что?
– Поди, поди к нему. Он просит твоей руки, – сказала графиня холодно, как показалось Наташе… – Поди… поди, – проговорила мать с грустью и укоризной вслед убегавшей дочери, и тяжело вздохнула.
Наташа не помнила, как она вошла в гостиную. Войдя в дверь и увидав его, она остановилась. «Неужели этот чужой человек сделался теперь всё для меня?» спросила она себя и мгновенно ответила: «Да, всё: он один теперь дороже для меня всего на свете». Князь Андрей подошел к ней, опустив глаза.
– Я полюбил вас с той минуты, как увидал вас. Могу ли я надеяться?
Он взглянул на нее, и серьезная страстность выражения ее лица поразила его. Лицо ее говорило: «Зачем спрашивать? Зачем сомневаться в том, чего нельзя не знать? Зачем говорить, когда нельзя словами выразить того, что чувствуешь».
Она приблизилась к нему и остановилась. Он взял ее руку и поцеловал.
– Любите ли вы меня?
– Да, да, – как будто с досадой проговорила Наташа, громко вздохнула, другой раз, чаще и чаще, и зарыдала.
– Об чем? Что с вами?
– Ах, я так счастлива, – отвечала она, улыбнулась сквозь слезы, нагнулась ближе к нему, подумала секунду, как будто спрашивая себя, можно ли это, и поцеловала его.
Князь Андрей держал ее руки, смотрел ей в глаза, и не находил в своей душе прежней любви к ней. В душе его вдруг повернулось что то: не было прежней поэтической и таинственной прелести желания, а была жалость к ее женской и детской слабости, был страх перед ее преданностью и доверчивостью, тяжелое и вместе радостное сознание долга, навеки связавшего его с нею. Настоящее чувство, хотя и не было так светло и поэтично как прежнее, было серьезнее и сильнее.
– Сказала ли вам maman, что это не может быть раньше года? – сказал князь Андрей, продолжая глядеть в ее глаза. «Неужели это я, та девочка ребенок (все так говорили обо мне) думала Наташа, неужели я теперь с этой минуты жена , равная этого чужого, милого, умного человека, уважаемого даже отцом моим. Неужели это правда! неужели правда, что теперь уже нельзя шутить жизнию, теперь уж я большая, теперь уж лежит на мне ответственность за всякое мое дело и слово? Да, что он спросил у меня?»
– Нет, – отвечала она, но она не понимала того, что он спрашивал.
– Простите меня, – сказал князь Андрей, – но вы так молоды, а я уже так много испытал жизни. Мне страшно за вас. Вы не знаете себя.
Наташа с сосредоточенным вниманием слушала, стараясь понять смысл его слов и не понимала.
– Как ни тяжел мне будет этот год, отсрочивающий мое счастье, – продолжал князь Андрей, – в этот срок вы поверите себя. Я прошу вас через год сделать мое счастье; но вы свободны: помолвка наша останется тайной и, ежели вы убедились бы, что вы не любите меня, или полюбили бы… – сказал князь Андрей с неестественной улыбкой.
– Зачем вы это говорите? – перебила его Наташа. – Вы знаете, что с того самого дня, как вы в первый раз приехали в Отрадное, я полюбила вас, – сказала она, твердо уверенная, что она говорила правду.
– В год вы узнаете себя…
– Целый год! – вдруг сказала Наташа, теперь только поняв то, что свадьба отсрочена на год. – Да отчего ж год? Отчего ж год?… – Князь Андрей стал ей объяснять причины этой отсрочки. Наташа не слушала его.
– И нельзя иначе? – спросила она. Князь Андрей ничего не ответил, но в лице его выразилась невозможность изменить это решение.
– Это ужасно! Нет, это ужасно, ужасно! – вдруг заговорила Наташа и опять зарыдала. – Я умру, дожидаясь года: это нельзя, это ужасно. – Она взглянула в лицо своего жениха и увидала на нем выражение сострадания и недоумения.
– Нет, нет, я всё сделаю, – сказала она, вдруг остановив слезы, – я так счастлива! – Отец и мать вошли в комнату и благословили жениха и невесту.
С этого дня князь Андрей женихом стал ездить к Ростовым.


Обручения не было и никому не было объявлено о помолвке Болконского с Наташей; на этом настоял князь Андрей. Он говорил, что так как он причиной отсрочки, то он и должен нести всю тяжесть ее. Он говорил, что он навеки связал себя своим словом, но что он не хочет связывать Наташу и предоставляет ей полную свободу. Ежели она через полгода почувствует, что она не любит его, она будет в своем праве, ежели откажет ему. Само собою разумеется, что ни родители, ни Наташа не хотели слышать об этом; но князь Андрей настаивал на своем. Князь Андрей бывал каждый день у Ростовых, но не как жених обращался с Наташей: он говорил ей вы и целовал только ее руку. Между князем Андреем и Наташей после дня предложения установились совсем другие чем прежде, близкие, простые отношения. Они как будто до сих пор не знали друг друга. И он и она любили вспоминать о том, как они смотрели друг на друга, когда были еще ничем , теперь оба они чувствовали себя совсем другими существами: тогда притворными, теперь простыми и искренними. Сначала в семействе чувствовалась неловкость в обращении с князем Андреем; он казался человеком из чуждого мира, и Наташа долго приучала домашних к князю Андрею и с гордостью уверяла всех, что он только кажется таким особенным, а что он такой же, как и все, и что она его не боится и что никто не должен бояться его. После нескольких дней, в семействе к нему привыкли и не стесняясь вели при нем прежний образ жизни, в котором он принимал участие. Он про хозяйство умел говорить с графом и про наряды с графиней и Наташей, и про альбомы и канву с Соней. Иногда домашние Ростовы между собою и при князе Андрее удивлялись тому, как всё это случилось и как очевидны были предзнаменования этого: и приезд князя Андрея в Отрадное, и их приезд в Петербург, и сходство между Наташей и князем Андреем, которое заметила няня в первый приезд князя Андрея, и столкновение в 1805 м году между Андреем и Николаем, и еще много других предзнаменований того, что случилось, было замечено домашними.