задача С требует положить на депозит 100 долл., а задача В желает снять со счета 1100 долл. Что произойдет, если обе задачи В и С попытаются обновить один и тот же счет одновременно?
Каким будет остаток на счете? Очевидно, остаток на счете в каждый момент времени не может иметь более одного значения. Задача А применительно к счету должна выполнять одновременно только одну транзакцию, т.е. мы сталкиваемся с проблемой координации задач. Если запрос задачи В будет выполнен на какую-то долю секунды быстрее, чем запрос задачи С, то счет приобретет отрицательный баланс. Но если задача С получит первой право на обновление счета, то этого не произойдет. Таким образом, остаток на счете зависит от того, какой задаче (В или С) первой удастся сделать запрос к задаче А. Более того, мы можем выполнять задачи В и С несколько раз с одними и теми же значениями, и при этом иногда запрос задачи В будет произведен на какую-то долю секунды быстрее, чем запрос задачи С, а иногда — наоборот. Очевидно, что необходимо организовать надлежащую координацию действий.
Для координации задач, выполняемых параллельно, требуется обеспечить связь между ними и синхронизацию их работы. При некорректной связи или синхронизации обычно возникает четыре типа проблем.
Проблема № 1 : «гонка» данных
Если несколько задач одновременно попытаются изменить некоторую общую область данных, а конечное значение данных при этом будет зависеть от того, какая задача обратится к этой области первой, возникнет ситуация, которую называют
Итак, несмотря на то, что мы хотели бы, чтобы наша программа позволяла одновременно обрабатывать множество операций по снятию денег со счета и вложению их на депозит, нам нужно координировать эти задачи в случае, если окажется, что операции снятия и вложения денег должны быть применены к одному и тому же счету. Всякий раз когда задачи одновременно используют модифицируемый ресурс, к ресурсному доступу этих задач должны быть применены определенные правила и стратегии. Например, в нашей программе поддержки банковских операций со счетами мы могли бы всегда выполнять любые операции по вложению денег
Проблема № 2: бесконечная отсрочка
Такое планирование, при котором одна или несколько задач должны ожидать до тех пор, пока не произойдет некоторое событие или не создадутся определенные условия, м ожет оказаться довольно непростым для реализации. Во-первых, ожидаемое событие или условие должно отличаться регулярностью. Во-вторых, между задачами следует наладить связи. Если одна или несколько задач ожидают сеанса связи до своего выполнения, то в случае, если ожидаемый сеанс связи не состоится, состоится слишком поздно или не полностью, эти задачи могут так никогда и не выполниться. И точно так же, если ожидаемое событие или условие, которое (по нашему мнению) должно произойти (или наступить), но в действительности не происходит (или не наступает), то приостановленные нами задачи будут вечно находиться в состоянии ожидания. Если мы приостановим одну или несколько задач до наступления события (или условия), которое никогда не произойдет, возникнет ситуация, называемая
Мы исходили из предположения о гарантированном существовании задач вложения денег на счет. Но если ни один из запросов на пополнение счетов не поступит, то что тогда заставит выполниться задачи снятия денег? И, наоборот, что, если будут без конца поступать запросы на пополнение одного и того же счета? Ведь тогда не сможет «пробиться» к счету ни один из запросов на снятие денег. Такая ситуация также может вызвать бесконечную отсрочку задач снятия денег.
Бесконечная отсрочка возникает при отсутствии задач вложения денег на счет или их постоянном поступлении. Необходимо также предусмотреть ситуацию, когда запросы на вложение денег поступают корректно, но нам не удается надлежащим образом организовать связь между событиями и задачами. По мере того как мы будем пытаться скоординировать доступ параллельных задач к некоторому общему ресурсу данных, следует предусмотреть все ситуации, в которых возможно создание бесконечной отсрочки. Методы, позволяющие избежать бесконечных отсрочек, рассматриваются в главе 5.
Проблема №3: взаимоблокировка
Взаимоблокировка — это еще одна «ловушка», связанная с ожиданием. Для демонстрации взаимоблокировки предположим, что в нашей программе поддержки электронного банка три задачи работают не с одним, а с двумя счетами. Вспомним, что задача А получает запросы от задачи В на снятие денег со счета, а от задачи С — запросы на вложение денег на депозит. Задачи А, В и С могут выполняться параллельно. Однако задачи В и С могут обновлять одновременно только один счет. Задача А предоставляет доступ задач В и С к нужному счету по принципу «первым пришел — первым обслужен». Предположим также, что задача В имеет монопольный доступ к счету 1, а задача С — монопольный доступ к счету 2. При этом задаче В для выполнения соответствующей обработки также нужен доступ к счету 2 и задаче С — доступ к счету 1. Задача В удерживает счет 1, ожидая, пока задача С не освободит счет 2. Аналогично задача С удерживает счет 2, ожидая, пока задача В не освободит счет 1. Тем самым задачи В и С рискуют попасть в
Форма взаимоблокировки в данном случае объясняется наличием параллельно выполняемых задач, имеющих доступ к совместно используемым данным, которые им разрешено обновлять. Здесь возможна ситуация, когда каждая из задач будет ожидать до тех пор, пока другая не освободит доступ к общим данным (общими данными здесь являются счет 1 и счет 2). Обе задачи имеют доступ к обоим счетам. Может случиться так,
вместо получения доступа одной задачи к двум счетам, каждая задача получит доступ одному из счетов. Поскольку задача В не может освободить счет 1, пока не получит К туп к счету 2, а задача С не может освободить счет 2, пока не получит доступ к счету 1, программа обслуживания счетов электронного банка будет оставаться заблокированной. Обратите внимание на то, что задачи В и С могут ввести в состояние бесконечной отсрочки и другие задачи (если таковые имеются в системе). Если другие задачи ожидают