Автор работы: Пользователь скрыл имя, 24 Сентября 2011 в 12:57, курсовая работа
В курсовом проекте предлагается спроектировать и разработать программу, обеспечивающую мультизадачность. В программе необходимо предусмотреть два визуальных процесса: один для ввода с контролем и корректировки данных (выполнять все виды корректировки – добавление, удаление, замену) и вывода результатов указанного в задании запроса и второй - для выполнения запроса.
1.ЗАДАНИЕ 3
2.ВВЕДЕНИЕ 4
3. ПРОБЛЕМЫ ПРИ СИНХРОНИЗАЦИИ ПОТОКОВ 5
3.1 СИНХРОНИЗАЦИЯ 6
4. ФУНКЦИИ WINAPI32 7
4.1 КРИТИЧЕСКИЕ СЕКЦИИ 7
4.2 ПОТОКИ 8
4.3 КАНАЛЫ 9
5.ГРАФИЧЕСКОЕ ОТОБРАЖЕНИЕ ВЗАИМОДЕЙСТВИЯ ПОТОКОВ И ОБМЕНА ДАННЫМИ МЕЖДУ НИМИ 12
6. ОПИСАНИЕ ОСНОВНЫХ СОБЫТИЙ ПРИЛОЖЕНИЯ 13
7.РЕЗУЛЬТАТЫ ТЕСТОВЫХ ПРОГОНОВ 14
8.ЛИСТИНГ ПРОГРАММЫ 18
8.1 UNIT1 18
8.2 UNIT2 26
9. ВЫВОД 29
10. СПИСОК ЛИТЕРАТУРЫ 30
Федеральное агентство по образованию
Ангарская
Государственная Техническая
Кафедра
“Вычислительные машины, комплексы,
системы и сети”.
Курсовая
работа
По курсу «Системное программное обеспечение»
По теме «Построение
оконных мультизадачных приложений,
организация обмена данными между процессами»
Выполнил:
cтудент гр. ВМК-02-2
Проверил:
ассистент
г. Ангарск
2005
СОДЕРЖАНИЕ
В курсовом проекте
предлагается спроектировать и разработать
программу, обеспечивающую мультизадачность.
В программе необходимо предусмотреть
два визуальных процесса: один для ввода
с контролем и корректировки данных (выполнять
все виды корректировки – добавление,
удаление, замену) и вывода результатов
указанного в задании запроса и второй
- для выполнения запроса.
Структура
записи:
Лекарства с реквизитами
Название лекарства | Номер аптеки | Цена упаковки | Количество упаковок |
Запрос: Выдать информацию о наличии некоторого лекарства в различных аптеках.
Обмен данными: через именованный канал.
Средства
синхронизации потоков: критические
секции.
Работая с Delphi, нужно иметь в виду: этот замечательный продукт не только упрощает разработку сложных приложений, он использует при этом все возможности операционной системы. Одна из возможностей, которую поддерживает Delphi, — это так называемые потоки (threads) или нити.
Потоки позволяют в рамках одной программы решать несколько задач одновременно. С недавних пор операционные системы для персональных компьютеров сделали это возможным.
Операционная система (ОС) предоставляет приложению некоторый интервал времени центрального процессора (ЦП) и в момент, когда приложение переходит к ожиданию сообщений или освобождает процессор, операционная система передает управление другой задаче. Теперь, когда компьютеры с более чем одним процессором резко упали в цене, а операционная система Windows NT может использовать наличие нескольких процессоров, пользователи действительно могут запускать одновременно более одной задачи.
Планируя время центрального процессора, Windows 95 или Windows NT распределяют его между потоками, а не между приложениями. Чтобы использовать все преимущества, обеспечиваемые несколькими процессорами в современных операционных системах, программист должен знать, как создавать потоки.
Определение потока довольно простое: потоки — это объекты, получающие время процессора. Время процессора выделяется квантами (quantum, timeslice). Квант времени — это интервал, имеющийся в распоряжении потока до тех пор, пока время не будет передано в распоряжение другого потока. Обратите внимание, что кванты выделяются не программам или процессам, а порожденным ими потокам. Как минимум, каждый процесс имеет хотя бы
один (главный) поток, но современные операционные системы, начиная с Windows 95 (для приверженцев Borland Kylix и Linux также), позволяют запустить в рамках процесса несколько потоков. Cамый простой пример их использования — приложения из состава Microsoft Office. К примеру, пакеты Excel и Word задействуют по несколько потоков. Word может одновременно корректировать грамматику и печатать, при этом осуществляя ввод данных с клавиатуры и мыши; программа Excel способна выполнять фоновые вычисления и печатать.
Если задачи приложения можно разделить на различные подмножества: обработка событий, ввод/вывод, связь и др., то потоки могут быть органично встроены в программное решение. Если разработчик может разделить большую задачу на несколько мелких, это только повысит переносимость кода и возможности его многократного использования.
Сделав приложение многопоточным, программист получает дополнительные возможности управления им. Например, через управление приоритетами потоков. Если один из них "притормаживает" приложение, занимая слишком много процессорного времени, его приоритет может быть понижен. Другое важное преимущество внедрения потоков — при возрастании "нагрузки" на приложение можно увеличить количество потоков и тем самым
снять проблему. Потоки упрощают жизнь тем программистам, которые разрабатывают приложения в архитектуре клиент/сервер.
Когда мы говорим "программа" (application), то обычно имеем в виду понятие, в терминологии операционной системы обозначаемое как "процесс". Процесс состоит из виртуальной памяти, исполняемого кода, потоков и данных. Процесс может содержать много потоков, но обязательно содержит, по крайней мере, один. Поток, как правило, имеет "в собственности" минимум ресурсов; он зависит от процесса, который и распоряжается виртуальной памятью, кодом, данными, файлами и другими ресурсами ОС. Почему мы используем потоки вместо процессов, хотя, при необходимости, приложение может состоять и из нескольких процессов? Дело в том, что переключение между процессами — значительно более трудоемкая операция, чем переключение между потоками. Другой довод в пользу использования потоков — то, что они специально задуманы для разделения ресурсов; разделить ресурсы между процессами (имеющими раздельное адресное пространство) не так-то просто.
К сожалению, простота создания потоков подчас "компенсируется" сложностью их применения. Две типичные проблемы, с которыми программист может столкнуться при работе с потоками, — это тупики (deadlocks) и гонки (race conditions).
Тупики
Вероятно, вы не раз наблюдали на трамвайной остановке следующую забавную картину
Тупики имеют место, когда поток ожидает ресурс, который в данный момент принадлежит
другому
потоку. Рассмотрим пример. Поток 1 захватывает
ресурс А, и для того чтобы продолжать
работу, ждет возможности захватить ресурс
Б. В тоже время Поток 2 захватывает ресурс
Б и ждет возможности захватить ресурс
А. Развитие этого сценария заблокирует
оба потока; ни один из них не будет исполняться.
Ресурсами могут выступать любые совместно
используемые объекты системы — файлы,
массивы в памяти, устройства ввода/вывода
и т. п. В информационных технологиях все
бывает сложнее. Откройте любой документ,
сопровождающий очередной пакет обновления
к любой версии Windows. Очень часто там можно
найти информацию об одной двух исправленных
ситуациях тупиков.
Гонки
Ситуация гонок возникает, когда два или более потока пытаются получить доступ к общему ресурсу и изменить его состояние. Рассмотрим следующий пример. Пусть Поток 1 получил доступ к ресурсу и изменил его в своих интересах; затем активизировался Поток 2 и модифицировал этот же ресурс до завершения Потока 1. Поток 1 полагает, что ресурс остался в том же состоянии, в каком был до переключения. В зависимости от того, когда
именно был изменен ресурс, результаты могут варьироваться — иногда код будет выполняться нормально, иногда нет. Программисты не должны строить никаких гипотез относительно порядка исполнения потоков, т. к. планировщик ОС может запускать и останавливать их в любое время.
Inc(i);
if i = iSomething then
DoSomething;
Здесь i — глобальная переменная, доступная из обоих потоков.
Пусть два или более потоков исполняют этот код одновременно. Поток 1 инкрементировал значение переменной i и хочет проверить ее значение для выполнения тех или иных условий. Но тут активизируется другой поток, который еще увеличивает значение i. В результате первый поток "проскакивает" мимо условия, которое, казалось бы, должно было быть выполнено. Возникновения как ситуаций гонок, так и тупиков можно избежать, если
использовать приемы, обсуждаемые ниже.
Главные
понятия для понимания
К возможным вариантам относятся четыре объекта, которые разработаны специально для синхронизации: событие (event), взаимное исключение (mutex), семафор (semaphore) и таймер (timer). Но кроме специальных объектов можно организовать ожидание и других
объектов, дескриптор которых используется в основном для иных целей, но может применяться и для ожидания. К ним относятся: процесс (process), поток (thread), оповещение об изменении в файловой системе (change notification) и консольный ввод (console input).
Косвенно
к этой группе может быть добавлена
критическая секция (criticalsection).
Критические секции – это механизм, предназначенный для синхронизации потоков внутри одного процесса. Как и мутекс, критическая секция может в один момент времени принадлежать только одному потоку, однако, она предоставляет более быстрый и эффективный механизм, чем мутексы. Перед использованием критической секции необходимо инициализировать её функцией:
procedure InitializeCriticalSection( var lpCriticalSection: TRTLCriticalSection);
После создания объекта поток, перед доступом к защищаемому ресурсу должен вызвать функцию:
procedure EnterCriticalSection(var lpCriticalSection: TRTLCriticalSection);
В качестве единственного параметра функциям EnterCriticalSection и LeaveCriticalSection необходимо передать адрес стрктуры типа TRTLCriticalSection, проинициализированной предварительно функцией InitializeCriticalSection.
Как работают критические секции? Если в этот момент ни один из потоков в процессе не владеет объектом, то поток становится владельцем критической секции и продолжает выполнение. Если секция уже захвачена другим потоком то выполнение потока, вызвавшего функцию EnterCriticalSection приостанавливается до её освобождения.
Таким образом гарантируется, что фрагмент кода, заключенный между вызовами функций EnterCriticalSection и LeaveCriticalSection, будет выполняться потоками последовательно, если все они работают с одной и той же критической секцией.
Поток, владеющий критической секцией, может повторно вызывать функцию EnterCriticalSection без блокирования своего исполнения. По завершению работы с защищаемым ресурсом поток должен вызвать функцию:
procedure LeaveCriticalSection( var lpCriticalSection: TRTLCriticalSection);
Эта функция освобождает объект независимо от количества предыдущих вызовов потоком функции EnterCriticalSection. Если имеются другие потоки, ожидающие освобождения секции, один из них становится её владельцем и продолжает исполнение. Если поток завершился, не освободив критическую секцию, её состояние становится неопределенным, что может вызвать блокировку работы программы.
Имеется возможность попытаться захватить объект без замораживания потока. Для этого служит функция: