Лабораторная работа № 2. Разработка многопоточных приложений

 

Цель: Программная реализация многопоточных приложений в операционной системе Windows.

 

Задачи:

1. Изучение теоретического материала по управлению потоками.

2. Составление алгоритма программы.

3. Программная реализация.

 

Ход работы:

1. Получить у преподавателя собственный вариант задания, который предусматривает распараллеливание работы на несколько потоков.

2. Используя изученные механизмы, разработать программу, реализующую полученное задание.

3. Написать отчет.

 

Ход защиты:

1. Продемонстрировать преподавателю программу, исполняющую несколько потоков.

2. Пояснить программный код приложения.

В современных ОС пользователям предлагается несколько типов параллельной работы, основными из которых являются процессы и потоки. Процессы – это программы на этапе выполнения. Потоки – это меньшая единица работы. Однако с точки зрения распределения ресурсов именно потоки являются главными, поскольку им, а не процессам предоставляется на определенное время центральный процессор для выполнения какой-либо работы. Рассмотрим несколько функций WinAPI, выполняющих некоторые операции над потоками.

 

Функция CreateThread создает поток, для выполнения внутри адресного пространства вызывающего процесса.

 

HANDLE CreateThread (

PSECURITY_ATTRIBUTES lpThreadAttributes,

   // атрибуты защиты потока

DWORD dwStackSize, // начальный размер стека потока, в байтах

PTHREAD_START_ROUTINE lpStartAddress,

// указатель на функцию потока

PVOID lpParameter, // параметр для нового потока

DWORD dwCreationFlags, // флаги создание потока

PDWORD lpThreadId

//указатель на возвращаемый идентификатор потока

);

 

При успешном завершении функции возвращается дескриптор нового потока. При неудачном завершении функции возвращается NULL.

 

Параметры:

LpThreadAttributes – Указатель на структуру SECURITY_ATTRIBUTES, которая определяет, может ли возвращенный дескриптор быть унаследован дочерними процессами. Если lpThreadAttributes NULL, то дескриптор не может быть унаследован.

 

DwStackSize – Определяет размер, в байтах, стека для нового потока. Если определен 0, то размер стека по умолчанию равен размеру стека порождающего потока. Стек распределяется автоматически в пространстве памяти процесса, и освобождается при завершении потока.

 

LpStartAddress – Начальный адрес нового потока. Это обычно адрес функции, объявленной с соглашением о вызовах WINAPI, которое принимает одиночный 32-разрядный указатель как параметр и возвращает 32-разрядный код завершения. Прототип: DWORD WINAPI ThreadFunc (LPVOID);

 

LpParameter – Определяет единственное 32-разрядное значение параметра, передаваемое потоку.

DwCreationFlags – Определяет дополнительные флажки, которые управляют созданием потока. Если флажок определен CREATE_SUSPENDED, то поток создается в состоянии ожидания, и не будет выполняться, пока не будет вызвана функция ResumeThread. Если это значение нуль, то поток выполняется немедленно после создания.

 

LpThreadId – Указатель на 32-разрядную переменную, которая получает значение идентификатора потока

 

Поток можно завершить принудительно с помощью вызова следующих функций Win 32 API:

VOID ExitThread (

DWORD ExitCode);// код завершения потока

и

VOID TerminateThread (

HANDLE hThread, // поток, который требуется завершить

DWORD ExitCode // код завершения потока

);

 

Для примера приведен фрагмент программы, которая вычисляет произведение всех чисел от 1 до 100.

...

// Функция потока

DWORD WINAPI ThreadFuction (PVOID Parametr)

{ int proizv = 1; // результат произведения

  int ii, *kk;

  kk = (int *) Parametr;

for (ii = *k; ii < (*kk) + 50; ii ++) proizv *= ii;

 

return proizv;

}

...

// код вызовов функций для создания потоков

DWORD idThread;

int k1 = 1; k2 = 51;

HANDLE h1, h2;

// Создается два потока в приостановленном состоянии

h1 = CreateThread (NULL, 0, ThreadFunction, &k1, CREATE_SUSPENDED, &idThread);

h2 = CreateThread (NULL, 0, ThreadFunction, &k2, CREATE_SUSPENDED, &idThread);

// Выполнение потоков

ResumeThread (h1);

ResumeThread (h2);

...

В данном коде встретилась весьма полезная Win 32 API функция
ResumeThread, которая возобновляет выполнение приостановленного потока и описанная как

DWORD ResumeThread (

HANDLE hThread // поток, который требуется возобновить

);

Если вызов этой функции успешен, то возвращается предыдущее значение счетчика простоев данного потока, в противном случае – 0 xFFFFFFFF.

 

Выполнение отдельного потока можно приостанавливать несколько раз (точно такое же число раз он должен возобновляться), а производится это вызовом функции SuspendThread, описанная как

DWORD SuspendThread (

HANDLE hThread // поток, который требуется приостановить

);

Поток может сообщить ОС, чтобы она не выделяла ему процессор определенное время, указанное в миллисекундах.

VOID Sleep (DWORD MilliSeconds);

 

В ОС Windows 2000/ XP есть также функция, которая находит и открывает поток по идентификатору.

HANDLE OpenThread (

DWORD DesiredAccess,

BOOL InheritHandle,

DWORD dwThreadId

);



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: