Пуши потоков неисповедимы
Сергей МАСЛИКОВ
В прошлой статье я рассказал об основных функциях и методах синхронизации потоков. Но, как вы
сами знаете, голая теория, не подкрепленная практикой, плохо воспринимается. Поэтому приступим
к написанию простенькой программы с использованием этих приемов. Писать будем на С++, но
можно и на ПеІрИ (а вообще — на чем хотите, главное, чтобы можно было подключить \Л/іпАРІ). Да,
еще один аспект, будем использовать только функции \Л/іп32 АРІ. Почему? Просто использование
потоков в проектах с МРС имеет свои особенности.
Продолжение, начало см. в М К, N s 41 (316)
И
так, начнем. Если у вас стоит Visual Studio, то создаем новый
проект W in32 A pp lication с именем
роток.
В окне выборо
типа проекта выберите A simple project, дальше жмем Fin-
ish. В основном файле проекта легко увидеть главную
функцию
WinMain ( )
. Начнем писать код, а потом будут объяснения.
#inclu de "s td a fx .h "
#inclu de «windows.h>
DWORD WINAPI Stream l (LPVOID) ;
DWORD WINAPI Stream2 (LPVOID) ;
HANDLE h stream l; //дескрипторы
HANDLE hstream 2; // создаваемых потоков
DWORD dwStreaml; //идентификаторы
DWORD dwStream2 ; / / потоков
CRITICAL_SECTION C ritS ec;
in t API ENTRY WinMain (HINSTANCE h ln sta n ce,
HINSTANCE h P revIn sta n ce,
LPSTR lpCmdLine,
in t nCmdShow)
{
/ / основной поток приложения
in t nMas [ 100 ] ; // произвольные
char NAME[100] ; // данные
In itia liz e C r itic a lS e c tio n (S C r itS e c );
hStream l=CreateThread(NOLL,0 ,Stream l,0 ,0 ,SdwStrea
m l);
hStream2=CreateThread(NULL,0 ,Stream2,0 ,0 ,&dwStrea
m2) ;
// продолжение основного потока
MessageBox (NULL, "START" , "COMM" , MBOK) ;
retu rn 0;
)
DWORD WINAPI Stream l (LPVOID)
{MessageBox(NULL,"START", "Stream l",M B_O K);
// строки рабочей функции потока 1
E n te rC ritic a lS e c tio n (& C ritS e c );
//выполнение каких-то расчетов
/ / обращение к общим данным
L e a v e C ritic a lS e c tio n (S C ritS e c );
/ / продолжаем выполнение рабочей функции
retu rn 0; / / ничего не возвращаем
}
DWORD WINAPI Stream2 (LPVOID)
{ MessageBox(NULL, " START", " Stream2" ,MB_ OK);
// строки рабочей функции потока 2
E n te rC ritic a lS e c tio n (R C ritS e c );
/ / обращение к общим данным
L e a v e C ritic a lS e c tio n (& C ritS ec );
/ / продолжаем выполнение
retu rn 0 ;
}
Ну что, начнем рассказывать, что к чему. Как видите,
программо — проще не бывает. О на только и делоет, что
выводит окно сообщений. Но ее вполне можно использовать
как шаблон. А если не лениться, можно и самому что-то
придумать © . В начоле объявлены глобальные переменные,
дескрипторы и идентификаторы потоков, переменная типа
c r it ic a l _ s e c t io n ,
которая потом инициализируется (см.
первую часть статьи), а также функции потоков. В этих самых
функциях существуют области, выделенные вызовом функции
E n te rC ritic a lS ec tio n (S C ritS e c )
и
L e a v e C ritic a lS e c -
tio n (s c r it s e c )
. Как уже говорилось в первой части статьи,
это помогает синхронизировать потоки. При вызове
E nter-
c r itic a ls e c tio n O
переменная, отвечающая за критическую
секцию, устанавливается в положение «занято» и теперь, если
другой поток захочет поработать с защищаемыми данными,
то его вежливо попросят подождать. Позже, когда при вызове
L e a v e C ritic a lS e c tio n (
) переменная типа
CRITICAL_SEC-
t io n
освобож дается, лю бой поток м ож ет обратиться к
защищаемым данным. Точнее, не любой, а тот, который успеет
первым © . В функциях потоков я нарочно не писал код по
обращ ению к данным, дабы не морочить вам и себе голову —
захотите, сами напишете. Все бы хорош о, да не всегда
возможно использовать критические секции. В более сложных
программах с большим числом пораллельных вычислений
будет довольно сложно совладать с солидным числом секций.
А если защищоемых данных много, и часть потоков использует
не все данные, а только одну переменную? Так что, теперь
тормозить другие потоки из-за одной переменной? Не-е,
пойдем другим путем.
Возьмем события. Во всех отношениях прекрасное средство.
И что мне особо нравится — они не привязаны к конкретному
действию. Мы можем установить или сбросить событие в
лю бой
точке
программы.
П равда,
чтобы
эффективно
пользоваться событиями, нужна тренировка, зокалка и
сноровка. Все теоретические сведения были изложены ранее,
посему приступим к примерам.
#inclu de «windows.h>
DWORD WINAPI Stream l (LPVOID) ; / / рабочие фунхции
потоков
DWORD WINAPI Stream2 (LPVOID); // потоков
CRITICAL_SECTION C ritS e c ;
HANDLE hEventsToC hild[2] ; //События оповещения
дочерних потоков
HANDLE hEventsFrom Child[2] ; // из дочерних потоков
HANDLE hEventsÄboutEnd[2]; / / уведомления о
прекращении работы
BOOL bTerm inate; / / используем для управления
потоками
in t API ENTRY WinMain (HINSTANCE h ln stance,
HINSTANCE h P revIn stan ce,
LPSTR lpCmdLine,
in t nCmdShow)
{HANDLE hStream [2] ; / / массив дескрипторов потоков
DWORD dwIDStreaml, dwIDStream2; //идентификаторы
потоков
In itia liz e C r it ic a lS e c tio n (& C r itS e c ); // инициируем
критическую секцию
/ / Создадим потоки
№ 9/336 28 февраля-07 марта 2005
предыдущая страница 40 Мой Компьютер 2005 09 читать онлайн следующая страница 42 Мой Компьютер 2005 09 читать онлайн Домой Выключить/включить текст