Ответ 1
Подумайте о состоянии гонки, используя традиционный пример. Скажем, у вас и у друга есть банкоматы для одного и того же банковского счета. Теперь предположим, что в учетной записи есть 100 долларов. Подумайте, что произойдет, когда вы попытаетесь снять 10 долларов, а ваш друг попытается снять 50 долларов в то же время.
Подумайте о том, что должно произойти. Банкомат должен взять ваш вход, прочитать то, что сейчас находится в вашей учетной записи, а затем изменить сумму. Обратите внимание, что в терминах программирования оператор присваивания представляет собой многоэтапный процесс.
Итак, назовите обе ваши транзакции T1 (вы снимаете 10 долларов США), а T2 (ваш друг снимает 50 долларов США). Теперь цифры внизу, слева, представляют временные шаги.
T1 T2
---------------- ------------------------
1. Read Acct ($100)
2. Read Acct ($100)
3. Write New Amt ($90)
4. Write New Amt ($50)
5. End
6. End
По завершении обеих транзакций, используя эту временную шкалу, которая возможна, если вы не используете какой-либо механизм блокировки, у этой учетной записи 50 долларов. Это на 10 долларов больше, чем нужно (ваша транзакция потеряна навсегда, но у вас все еще есть деньги).
Это называется состоянием гонки. Вы хотите, чтобы транзакция была сериализуемой, то есть вне зависимости от того, как вы чередовываете выполнение отдельных команд, конечный результат будет таким же, как для некоторого последовательного расписания (что означает, что вы запускаете их один за другим без перемежения) те же транзакции. Решением также является введение блокировки; однако неправильная блокировка может привести к мертвой блокировке.
Тупик возникает, когда возникает конфликт общего ресурса. Это похоже на Catch-22.
T1 T2
------- --------
1. Lock(x)
2. Lock(y)
3. Write x=1
4. Write y=19
5. Lock(y)
6. Write y=x+1
7. Lock(x)
8. Write x=y+2
9. Unlock(x)
10. Unlock(x)
11. Unlock(y)
12. Unlock(y)
Вы можете видеть, что тупик возникает в момент времени 7, потому что T2 пытается получить блокировку на x
, но T1 уже удерживает блокировку на x
, но он ожидает блокировки для y
, которую имеет T2.
Это плохо. Вы можете превратить эту диаграмму в график зависимостей, и вы увидите, что существует цикл. Проблема здесь в том, что x и y - ресурсы, которые могут быть изменены вместе.
Один из способов предотвратить такую проблему взаимоблокировки с несколькими объектами блокировки (ресурсами) - это ввести упорядочение. Вы видите, что в предыдущем примере T1 заблокирован x
, а затем y
, но T2 заблокирован y
, а затем x
. Если обе транзакции привязаны к некоторому правилу упорядочения, в котором говорится: "x
всегда будет заблокировано до y
", тогда эта проблема не возникнет. (Вы можете изменить предыдущий пример с учетом этого правила и не видеть, что тупик происходит).
Это тривиальные примеры, и на самом деле я только что использовал примеры, которые вы, возможно, уже видели, если вы приняли какой-либо курс обучения по этому курсу. На самом деле решение проблем с тупиками может быть намного сложнее, потому что вы, как правило, имеете более чем пару ресурсов и пару транзакций, взаимодействующих друг с другом.
Надеюсь, это поможет немного. Как всегда, используйте Википедию в качестве отправной точки для концепций CS: