- •6.Определение потока
- •12.Создание потоков в Windows
- •24.Программная реализация синхронизации
- •30.События Windows
- •36.Способы передачи данных между процессами
- •42.Обработка вложенных исключений
- •48.Создание и удаление кучи в Windows
- •54.Концепция порта завершения
- •60.Распределение и освобождение локальной памяти потока
6.Определение потока
Определение потока тесно связано с последовательностью действий процессора во время исполнения программы.Исполняя программу, процессор последовательно выполняет инструкции программы, иногда осуществляя переходы в зависимости от некоторых условий. Такая последовательность выполнения инструкций программы называется потоком управления внутри программы. Поток управления можно представить как нить в программе, на которую нанизаны инструкции, выполняемые микропроцессором. Поэтому часто поток управления также называется нитью (thread). программа является многопоточной, если в ней может одновременно существовать несколько потоков. Сами потоки в этом случае называются параллельными. Если в программе одновременно может существовать только один поток, то такая программа называется однопоточной.
12.Создание потоков в Windows
Создается поток функцией createThread, которая имеет следующий прототип:
HANDLE CreateThread(
LРSECURITY_ATTRIBUTES lpThreadAttributes, // атрибуты защиты
DWORD dwStackSize, // размер стека потока в байтах
LPTHREAD_START_ROUTINE IpStartAddress, II адрес функции
LPVOID lpParameter, // адрес параметра
DWORD dwCreationFlags, // флаги создания потока
LPDWORD lpThreadld // идентификатор потока
);
При успешном завершении функция CreateThread возвращает дескриптор созданного потока и его идентификатор, который является уникальным для всей системы. В противном случае эта функция возвращает значение null.
Для создания потоков можно также использовать макрокоманду _beginthreadex, которая описана в заголовочном файле process.h и имеет те же параметры, что и функция createThread.
18.Завершение процессов в Windows
Процесс может завершить свою работу вызовом функции Exitprocess, которая имеет следующий прототип:
VOID ExitProcess(
UINT uExitCode // код возврата из процесса
) ;
При вызове функции Exitprocess завершаются все потоки процесса с кодом возврата, который является параметром этой функции. При выполнении этой функции система посылает динамическим библиотекам, которые загружены процессом, сообщение dll_process_detach, которое говорит
том, что динамическую библиотеку необходимо отсоединить от процесса.
Один процесс может быть завершен другим при помощи вызова функции TerminateProcess, которая имеет следующий прототип:
HANDLE
hProcess,
UINT
uExitCode
Если функция TerminateProcess выполнилась успешно, то она возвращает ненулевое значение. В противном случае возвращаемое значение равно false. Функция TerminateProcess завершает работу процесса, но не освобождает все ресурсы, принадлежащие этому процессу. Это происходит потому, что при выполнении этой функции система не посылает динамическим библиотекам, загруженным процессом, сообщение о том, что библиотеку необходимо отсоединить от процесса. Поэтому эта функция должна вызываться только в аварийных ситуациях при зависании процесса.
24.Программная реализация синхронизации
синхронизация потоков может осуществляться чисто программными средствами, используя глобальные переменные. Для постановки ЭТОЙ задачи рассмотрим два потока thread_l И thread_2, которые работают следующим образом. Поток thread_i выполняет некоторые действия, а затем ждет наступления события event, после которого выполняет другие действия. В свою очередь поток thread_2 также выполняет некоторые действия, а после их завершения оповещает поток thread_i о наступлении события event. Затем ПОТОК thread_2 выполняет оставшиеся действия. Такая синхронизация работы потоков и называется задачей условной синхронизации.
Схематически программный КОД ПОТОКОВ thread_l И thread_2, который решает поставленную задачу условной синхронизации, приведен ниже.
bool event = false; // событие event
void thread_l() // поток thread_l
{
actions_before_event() ;
while(!event);
actions after event()
;// действия до наступления события //
ждждем, пока событие не произошло //
дедействия после наступления события
void thread_2()// поток thread_2
some_actions(); event = true; other_actions();
// действия, о которых оповещает событие // отмечаем о наступлении события // действия, происходящие после события
— фактически наступление некоторого события равносильно выполнению некоторого действия. Поэтому событие часто и определяют как действие. В потоке thread_i это действие обозначается функцией some_actions ().
для решения задачи условной синхронизации для двух потоков достаточно определить глобальную булеву переменную event, начальное значение которой установить в false. Затем в потоке thread_2 установить значение этой переменной В true после наступления события event. Тогда ПОТОК thread_l ждет наступления события event посредством оператора while ( ! event), который циклически проверяет значение булевой переменной event до тех пор, пока эта переменная не примет значение true. Очевидно, что подобным образом задача условной синхронизации может быть решена и для произвольного количества потоков, ждущих наступления события event.
