Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
98
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

Работа 14. Защита данных с помощью критической секции

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

Состав глобальных переменных:

  • структурная переменная CritSectтипаCRITICAL_SECTION;

  • целочисленная переменная nBalanceдля остатка денег на счете;

  • булева переменная bGo, управляющая выполнением потоков;

  • две целочисленные переменные nDeals1иnDeals2для отсчета числа выполненных банковских операций (транзакций) первым и вторым потоками;

  • два дескриптора создаваемых в программе файлов;

  • переменная типа DWORD, требуемая для операций записи в файл.

Локальные переменные в главной функции WinMain():

  • массив из двух переменных hThreads[2]типаHANDLEдля хранения дескрипторов создаваемых потоков;

  • две переменные типа DWORDдля хранения идентификаторов создаваемых потоков;

  • символьный массив достаточной длины для формирования итогового сообщения.

Состав главной функции WinMain():

  • инициализация критической секции вызовом функции InitializeCriticalSection();

  • создание двух файлов с произвольными именами для записи в них информации о произведенных транзакциях;

  • создание двух вторичных потоков с рабочими функциями Thread1иThread2;

  • установка переменной bGo, разрешающей выполнение обоим потокам;

  • “пустой” цикл while(nBalance>=1), останавливающий выполнение первичного потока (функцииWinMain()) до полного истощения денег на счете;

  • после выхода из цикла while()сброс переменнойbGo;

  • ожидание завершения обоих потоков с помощью функции WaitForMultipleObjects();

  • формирование в символьном массиве (с помощью функции wsprintf()) итогового сообщения, включающего исходную сумму счета, количество транзакций первого и второго потоков, остаток денег на счете, а также сумму, снятую со счета обоими потоками вместе;

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

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

Рабочие функции потоков ничем не отличаются друг от друга за исключением того, что первый поток, выполнив транзакцию, инкрементирует переменную nDeals1, а второй – переменнуюnDeals2.

Состав рабочих функций потоков:

  • цикл while(bGo), в который включается весь текст рабочей функции (за исключением последнего предложенияreturn 0);

  • вход в критическую секцию (функция EnterCriticalSection());

  • чтение в локальную переменную потока nLocalBalanceтекущего содержимого глобальной переменнойnBalance(суммы денег на счете);

  • проверка с помощью предложения if(nLocalBalance >=1)наличия денег на счете (все дальнейшие операции выполняются в блокеif, т. е. лишь при положительном результате этого сравнения);

  • уменьшение значения переменной nLocalBalance на единицу (снятие со счета);

  • инкремент переменной nDealsилиnDeals2;

  • формирование символьной строки с текущей суммой на счете (значение переменной nLocalBalance);

  • запись этой строки в файл, соответствующий данному потоку (эта операция введена для увеличения времени работы функции потока и повышения вероятности ее прерывания с передачей управления другому потоку);

  • в качестве последней операции перенос значения переменной nLocalBalanceв глобальную переменнуюnBalance;

  • после закрытия блока ifвыход из критической секции вызовом функцииLeaveCriticalSection()

  • после закрытия блока whileзавершающий операторreturn 0и закрытие рабочей функции потока.

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

Видно, что при начальной сумме 100000 единиц со счета было снято в общей сложности 189580 единиц, причем на счете еще осталась некоторая сумма.

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