/
Tags: информатика
Text
Лабораторная работа №
3
. Потоки в Windows (2 ч.)
Потоки
. Создание и завершение пот
о
ков.
Приостановка и
возобновление потоков. Многопоточные приложения.
Потоком
управления
(
thread
)
наз
ывает
ся
последовательность инструкций
программы, выполняемая
процессором. Иногда
для этого
используется термин нить.
Программа, использующая одновременно несколько
потоков управления называется
многопоточной
.
Просмотреть количество потоков, запущенных
прил
ожением можно при помощи стандартного «Диспетчера
задач» Windows.
Более подробную информацию можно получить,
например, при помощи Sysinternals Process Explorer. Он
отображает не только количество потоков, но и позволяет
увидеть их TID, адреса функций, ко
торые в них выполняются,
состояние, а также приостановить, возобновить или завершить
отдельные потоки.
Содержимое памяти, к которому имеет доступ поток,
называется
контекстом потока
. По отношению к
обрабатываемым данным
,
выполняемые в потоках функции
дел
ятся на
потокобезопасные
и
потоконебезопасные
.
Потокобезопасные функции независимо от количества
параллельных вызовов корректно изменяют используемые
данные и блокируют доступ к ресурсам, которые они
используют на время их использования.
В Windows потоком
называется объект ядра, которому ОС
выделяет процессорное время для выполнения программы.
Каждый поток в Windows имеет собственный
дескриптор
и
уникальный идентификатор
(аналогично ProcessID у
процессов).
Для создания потока используется функция CreateThre
ad
со следующим прототипом
:
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
В случае успешного завершен
ия функция возвращает
дескриптор созданного потока или
NULL
в случае ошибки.
Параметр
dwStackSize
задает размер стека потока,
значение
0
означает, что система самостоятельно выделяет
под стек блок памяти минимального размера.
Параметр lpStartAddress указыв
ает на исполняемую
в
поток
е
функцию. Такая функция должна быть описана
согласно следующему прототипу:
DWORD WINAPI имя_функции_потока (
LPVOID lpParameter
);
Например:
DWORD WINAPI MyThreadFunction (LPVOID myParam);
Параметр
lpParameter
–
это
передаваемы
й
в функцию
потока параметр, который является указателем на тип void.
Параметр
dwCreationFlags
определяет начальное
состояние созданного потока:
0
–
функция потока начинает выполняться сразу после
создания потока;
CREATE_SUSPENDED
–
поток создается в приос
тановленном
состоянии. Для его запуска нужно использовать функцию
ResumeThread
.
Выходной параметр
lpThreadId
указывает на переменную,
в которую
Windows
поместит идентификатор созданного
потока. Допускается его установка в
NULL
, тогда
Windows
не
будет возвр
ащать идентификатор потока.
Пример простейшей программы, создающей несколько
потоков исполнения:
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI WorkerThread(LPVOID param)
{
while(
true
)
{
cout << *((
int
*)param) << " ";
}
}
int main()
{
HANDLE hThread;
DWORD ThreadID;
DWORD Num = 2;
hThread = CreateThread(NULL, 0, WorkerThread,
(
void
*)&Num, 0, &ThreadID);
if(hThread == NULL)
{
cout <<
"
ошибка
"
<< GetLastError() << endl;
system(
"pause"
);
return
-
1;
}
while(
tru
e
)
{
cout << 1 << " ";
}
return 0;
}
Задание 1.
На основе приведенных выше материалов
с
оздайте в
Microsoft Visual Studio
консольное приложение с 2
-
3 потоками исполнения. Соберите проект и проверьте с
помощью Диспетчера задач
Windows
, что потоки успеш
но
запущены.
Для
выхода из
потока
он может
использ
ова
т
ь
вызов
оператора
return
или
функции
ExitThread
со следующим
прототипом:
VOID ExitThread(
DWORD dwExitCode
);
Кроме того, один поток может завершить другой поток с
помощью вызова функции
TerminateThr
ead
:
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode
);
Кроме завершения, поток может быть приостановлен на
некоторое время с помощью функции
SuspendThread
:
DWORD SuspendThread(
HANDLE hThread
);
Для возобновления остановленного таким образом
потока
используется функция
ResumeThread
:
DWORD ResumeThread(
HANDLE hThread
);
Задание
2.
Разработайте приложение, которое будет
запускать дополнительный поток исполнения, в котором
проигрывать какую
-
либо мелодию
с
помощ
ью
функции
Beep()
.
Основной поток
должен принимать команды пользователя и в
соответствии с ними приостанавливать и
ли
возобновлять
работу потока, проигрывающего звук. Отследите с помощью
Process Explorer’а состояние контролируемого потока.
Функция
Beep
генерирует тон заданной частоты и
во
спроизводит его через
PC
-
спикер
(при его наличии)
.
Функция является синхронной, поэтому её вызов лучше
выполнять в отдельном потоке. Прототип функции:
BOOL WINAPI Beep(
DWORD dwFreq,
DWORD dwDuration
);
dwFreq
–
частота звука в герцах (может принимать
значения от
37
до
32767
; ноте «ля» первой октавы соответствует
440
Hz,
разница между двумя соседними нотами ~
50
Hz);
dwDuration
–
длительность звука в секундах.
Поток может сам приостановить свое выполнение с
помощью функции Sleep:
VOID Sleep(
DWORD dwMill
iseconds
);
Здесь параметр
dwMilliseconds
задает интервал, на
который приостанавливается выполнение потока. В случае
задания константы
INFINITE
поток будет приостановлен
на
всегда, в случае задания значения
0
–
поток просто
завершит свое выполнение на текущ
ий выделенный ему квант
процессорного времени.
Задание
3
.
Разработайте приложение, вычисляющее сумму
элементов целочисленной матрицы
N
x
N
.
Для того, чтобы
получить преимущество при выполнении на
многопроцессорной системе или на многоядерном процессоре
п
р
ограмма должна выполнять работу с помощью
N
потоков
выполняющихся параллельно (ближайшей аналогией будет
бригада строителей, строящих одну и ту же стену).