Программирование для Windows NT

       

Последовательный доступ к ресурсам


При создании мультизадачных приложений часто возникает необходимость обеспечить последовательный доступ параллельно работающих задач к какому-либо ресурсу. Типичным примером может послужить приложение MULTISDI, в котором несколько задач одновременно рисуют в одном окне приложения, пользуясь контекстом отображения и графическими функциями. Другой пример - данные, которые изменяются и читаются несколькими задачами сразу. Процедуры изменения и чтения в данном случае необходимо выполнять строго последовательно, иначе данные могут быть искажены.

Приведем еще один типичный пример, когда необходимо обеспечить последовательный доступ к ресурсу.

Пусть на счету в банке у фирмы лежит 2 млн. долларов. Два торговых агента фирмы одновременно пытаются сделать покупки, причем стоимость товара в обоих случаях равна 1,5 млн. долларов. При этом процесс покупки заключается в том, что вначале программа получает запись базы данных, в которой хранится общая сумма, затем она вычитает из нее стоимость товара и сохраняет новое значение общей суммы.

Допустим, что для выполнения покупки программа создает по одной задаче на каждого торгового агента, и эти задачи будут работать одновременно. Если не предусмотреть средства синхронизации доступа к записи базы данных, возможно возникновение такой ситуации, когда процессы покупки (получение общей суммы - вычитание стоимости товара - сохранение нового значение общей суммы), выполняемые этими двумя задачами, перекроются во времени.

К чему это может привести?

Если перекрытия во времени не произойдет, то вначале задача, запущенная для первого торгового агента, прочитает общую сумму, которая будет равна 2 млн. долларов. Затем она вычтет из нее стоимость покупки и запишет результат (500 тыс. долларов) обратно. Второй торговый агент уже не сможет сделать покупку, так как он обнаружит, что на счету осталось слишком мало денег.

В том случае, если покупки делаются одновременно, события могут развиваться в следующей последовательности:

  • первый агент получает значение общей суммы (2 млн. долларов);

  • второй агент получает значение общей суммы (2 млн. долларов);


  • первый агент вычитает из этой суммы стоимость товара (1,5 млн. долларов) и записывает результат (500 тыс. долларов) в базу данных;


  • второй агент вычитает из общей суммы стоимость товара и записывает результат в базу данных


  • Кто пострадает в данной ситуации?

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

    Ошибку можно было бы предотвратить, если во время выполнения любой задачей операции изменения текущего счета запретить доступ к этому счету других задач. Можно предложить следующий вариант сценария совершения покупок:

    • задача изменения счета проверяет, не заблокирован ли доступ к соответствующей записи базы данных. Если заблокирован, задача переводится в состояние ожидания до разблокировки. Если же доступ не заблокирован, задача выполняет блокировку такого доступа для всех других задач;


    • задача получает значения общей суммы;


    • задача выполняет вычитание стоимости купленного товара из общей суммы и записывает результат в базу данных;


    • задача разблокирует доступ к записи базы данных


    • Таким образом, при использовании приведенного выше сценария во время попытки одновременного изменения значения счета двумя торговыми агентами задача, запущенная чуть позже, перейдет в состояние ожидания. Когда же первый агент сделает покупку, задача второго агента получит правильное значение остатка (500 тыс. долларов), что не позволит ему приобрести товар на 1,5 млн. долларов.

      В программном интерфейсе операционной системы Microsoft Windows NT имеются удобные средства организации последовательного доступа к ресурсам. Это критические секции, объекты взаимно исключающего доступа Mutex и блокирующие функции изменения содержимого переменных.


      Содержание раздела