М И Н И СТ Е РСТ В О О БРА ЗО В А Н И Я РО ССИ Й СК О Й Ф Е Д Е РА Ц И И В О РО Н Е Ж СК И Й ГО СУ Д А РСТ В Е Н Н Ы Й У...
6 downloads
246 Views
244KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
М И Н И СТ Е РСТ В О О БРА ЗО В А Н И Я РО ССИ Й СК О Й Ф Е Д Е РА Ц И И В О РО Н Е Ж СК И Й ГО СУ Д А РСТ В Е Н Н Ы Й У Н И В Е РСИ Т Е Т Ф акультетп рикладной математикиимеханики К а ф едр а т ехн и ческой ки бер н ет и ки и а вт ом а т и ческого р егу ли р ова н и я
Р азраб о тка м н о г о п о то чн ы х п рило ж ен ий М етодичес киеуказания к курс у « Системноеип рикладноеп рог раммное об есп ечение» для с тудентов 3 курсад/о ф акультетаП М М
Составители: Рудалев В .Г., К ры ж ановская Ю .А .
В оронеж , 2001 1
В методических указаниях оп ис ы ваю тся основы создания мног оп оточны х п рилож ений для оп ерационны х систем Windows 95/98/NT/2000. И злож енаметодикаис п ользования стандартны х средств интерф ейс ап рикладног о п рог раммирования API Win32 исп ециализированны х классов среды п рог раммирования Delphi. М етодические указания рас считаны настудентов 3 курсад.о. ф -таП М М , имею щ их начальное п редставление об архитектуре Win32 инавы кип рог раммирования в средеDelphi 4.0 – 5.0. Рецензент: доценткаф едры М О Э В М Ю .Т .Свиридов
С оде р ж ан и е 1. О сновны еп онятия… … … … … … … … … … … … … … … … … … 2 2. Созданиеп отоков средствамиAPI… … … … … … … … … … … ..4 3. К лас сTThread… … … … … … … … … … … … … … … … … … … … 7 4. Синхронизация п отоков… … … … … … … … … … … … … … ..… 12 5. Задания для самос тоятельной раб оты … … … … … … … … … ...18 Литература… … … … … … … … … … … … … … … … … … … … … … 19
1. О сн овн ы епон яти я П от ок (Thread, н и т ь выполн ен и я) – исп олняемая сущ ность пр оцесса . П р оцесс вклю чаетв себ я загруж енную в оп еративную п амять исп олняемую п рог рамму, виртуальное адресное п ространство, системны е ип ользовательские ресурсы , вы деленны е п рог рамме, и один илинесколько пот оков (н и т ей) вы п олнения. В каж дом п роцессевсег данеявно (незаметно для п рог раммистаинезависимо отег о воли) п рис утствуетодин осн овн ой пот ок пр и лож ен и я, остальны е п отокип ринеоб ходимостип рог раммистп иш етсам. П отокивы п олняю тся п араллельно в виртуальном адресном п рос транстве п ородивш ег о их п роцессаи разделяю т ресурсы этог о п роцесса. Е диницей мног озадачностив Windows является п оток, ане п роцесс. П оток мож но рассматривать как автономно раб отаю щ ую и уп равляемую часть п рилож ения, амног оп оточнос ть п рилож ения – как мног озадачность внутри п рог раммы . Средип ричин, п об уж даю щ их создавать именно мног оп оточны еп рилож ения, п реж девсег о следуетвы делить следую щ ие. П овы ш е н и ен аде ж н ости пр огр ам м ы . Зацикливание основног о п отока п рилож ения п олностью б локирует ег о раб оту, п риэтом п рилож ение мож ет б ы ть заверш ено лиш ь п рип омощ идисп етчеразадач (Task Manager), что, как п равило, соп ровож дается п отерей нес охраненны х данны х. П оэтому « неб лагонадеж ны е» вы числительны еф рагменты рекомендуется п еренос ить изосновног о п отокав отдельны е доп олнительны е п отоки, п редусмотрев возмож ность их досрочног о заверш ения (см. лаб .раб оты 1,2). 2
П овы ш е н и еб ы стр оде йстви я, экон ом и я р е сур сов и р асш и р е н и ефун кци он альн ы х возм ож н осте й пр огр ам м ы . М ног оп оточность п озволяет п араллельно вы п олнять отдельны е участкип рог раммы наЭ В М снесколькимип роцессорами, или вы п олнять их наодном п роцессоре « п севдоп араллельно», исп ользуя механизм вы тесняю щ ей мног озадачнос ти Windows. Н ап ример, различны е п отоки в Microsoft Word одновременно п ринимаю т п ользовательский ввод, п роверяю т орф ог раф ию в ф оновом реж име ип ечатаю т документ. Microsoft Excel с троит диаг раммы ивы п олняетматематическиерасчеты в ф оновом реж име. Сервер б азданны х для ответанакаж ды й зап росклиентазап ускает отдельны й п оток, в п ротивном случаеп риш лос ь б ы либ о зап ускать отдельную коп ию сервера, нап расно расходуя ресурсы , либ о чрезвы чайно ус лож нять лог ику ег о раб оты . И нтерф ейсп рикладны х п рог рамм разнооб разятанимация, восп роизведениезвукаит.п ., вы п олняемы еотдельны мип отоками. Н ап омним, что п ривы тесняю щ ей мног озадачностип отокивы п олняю тся п оп еременно, время п роцессоравы деляется п отокам ква н т а м и (около 19 мс). О С вы тесняет п оток, ког даистечет ег о квант иликог данаочередип оток сб ольш им п риоритетом. П риоритеты п ос тоянно п ересчиты ваю тся, чтоб ы изб еж ать моноп олизации п роцессора одним п отоком. С каж ды м п отоком связан кон т екст – структура, содерж ащ ая инф ормацию о состояниип отока, в том числесодерж имое рег истров п роцессора. (Более п одроб ную инф ормацию мож но п олучить, изучив структуру TContext в ф айле windows.pas изп ап ки..\borland\delphi4\source\rtl\win.) В ы теснение п отокасоп ровож дается сохранением содерж имог о рег истров в контексте, ап олучениеп отоком квантавремени- восстановлением рег истров изконтекста. К числу тип ичны х п роб лем, возникаю щ их п риисп ользованиип отоков, относятся так назы ваемы егон ки и т у пи ки . К онф ликт(collision) гон ок п роисходит, ког дадвап отокап ы таю тс я изменить одну иту ж е об ластип амяти. Е слине п редп ринимать сп ециальны х мер синхронизации, результатб удетнеп редс казуемы м и зависимы м оттог о, какой изп отоков « усп еетп ервы м». Н ап ример, насчету в б анкеб ы ло 1000$. П ервы й п оток снял 300$ со счетав б анке, но остаток зап исать не усп ел, так как б ы л вы тес нен друг им п отоком. В торой п оток снял деньг и999$ (разумеетс я, с1000$), зап исал остаток 1$, но тут уп равление вновь п олучил п ервы й п оток и, зап исав ос таток 700$, уничтож ил « следы деятельности» второг о п отока. Ту пи ки возникаю т, ког да п отокиож идаю трес урс ы , занимаемы едруг друг ом. Н ап ример, п оток А держ ит рес урс1, ож идая ког дап оток Б отдас т ему ресурс2, Н о п оток Б ресурснеотдает, так как ж детресурса1. В результатеоб ап отокаб ездействую т. О б е п роб лемы мог ут б ы ть реш ены сп омощ ью средств синхронизациип отоков, оп исы ваемы х ниж е.
3
2. С о здан ие п о то ко в средствам и API И сп ользование б иб лиотекиAPI Win32 – наиб олее мощ ны й иуниверсальны й сп ос об раб оты сп отоками наб ольш инстве язы ков п рог раммирования [6]. И мею щ иеся в Delphi сп ециализированны е классы являю тся надстройкой над соответствую щ имиф ункциямиAPI. П оток создается сп омощ ью ф ункцииAPI, возвращ аю щ ей дескрип тор п отока function CreateThread ( Attr: Pointer; // Адрес атрибутов безопасности Stack: Dword; // Размер стека для потока Start: Pointer; // Начальный адрес потока par: pointer; // Аргументы потока flag: Dword; // флаг создания var ID: Dword // Возвращаемый идентификатор потока ): THandle; // Результат функции – дескриптор потока
П араметр Attr об ы чно задается равны м Nil, что соответствуетатриб утам б езоп асностип о умолчанию (б олееп одроб но см. раздел Win32 Programmer’s Reference в сп равочной системеDelphi). П араметр Stack задаетразмер стекадля п отока. Е слион равен нулю , то размер стекасовп адаетсразмером стекаос новног о п отокап рилож ения. П араметр Start – основной. Ч ерезнег о п ередается адресф ункции, вы зы ваемой п ри зап уске п отока. Э та ф ункция об язана возвращ ать результат тип а longint, иметь один п араметр тип аPointer. П риоп исанииф ункциинеоб ходимо указы вать атриб утstdcall (см.листинг ), оп ределяю щ ий стандартны й для API сп особ вы зоваф ункции(зап ись арг ументов в с тек в п орядке сп рава-налево, очистка стекап ризаверш ениираб оты самой п одп рог раммой). П араметр Par – указатель наструктуру (зап ись), содерж ащ ую арг ументы , п ередаваемы ев п роцедуру п отока. Е слиPar=Nil, то арг ументы отсутствую т. Е сли задать ф лаг с оздания flag, равны й нулю , то п оток сразу начнетраб оту, аеслиуказать константу CREATE_SUSPENSED, то п оток начнетраб оту только п ослевы зоваф ункции function ResumeThread (hThread: THandle): Dword; Здесь hThread – дескрип тор созданног о п отока. П риостановить п оток мож но сп омощ ью ф ункции function SuspendThread (hThread: THandle): Dword; Ч тоб ы досрочно заверш ить п оток, следуетвы звать ф ункцию SuspendThread , азатем - ф ункцию function CloseHandle(hThread: THandle): Dword; 4
П роиллю стрируем исп ользованиеAPI изп рог рамм наDelphi следую щ ей лаб ораторной раб отой. П ростой п роектб удетвы п олнять расчеттрадиционны м сп особ ом и, для сравнения, сп омощ ью доп олнительног о п отока. Лаб о рато рн ая раб о та № 1 1. Создав новы й п роект, рас п олож им наф ормекноп киснадп исями « С п отоком», « Безп отока», « П риостановить», « П родолж ить». 2. Н ап иш ем ф ункцию func исоздадим об раб отчикисоб ы тий так, чтоб ы листинг модуля п ринял вид: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: procedure Button2Click(Sender: procedure Button3Click(Sender: procedure Button4Click(Sender: private { Private declarations } public { Public declarations } end;
TObject); TObject); TObject); TObject);
var Form1: TForm1; implementation var hThread: THandle; // Дескриптор потока ThreadID: DWord; // Идентификатор потока {$R *.DFM} // Эта функция далее будет выполняться внутри потока function func (p: pointer): longint; stdcall; var i: integer; dc: hDc;//дескриптор контекста графического устройства s: string; begin dc:=GetDc(form1.handle);//Получаем контекст формы for i:=0 to 10000000 do begin s := IntToStr(i); // Выводим в цикле число, 5
// используя функцию API textout(dc,10,10,pchar(s), length(s)); end; ReleaseDC(Form1.handle,dc); //Освобождаем контекст end; procedure TForm1.Button1Click(Sender: TObject); begin // Вызываем функцию Func в составе потока. Для этого // создаем поток и передаем в него адрес функции hThread := CreateThread(Nil,0,@Func,Nil,0,THreadID); if hThread=0 then ShowMessage('No THread'); end; procedure TForm1.Button2Click(Sender: TObject); begin SuspendThread(hThread); // Приостанавливаем поток end; procedure TForm1.Button3Click(Sender: TObject); begin ResumeThread(hThread); // Продолжаем поток end; procedure TForm1.Button4Click(Sender: TObject); begin Func(nil); // Вызываем функцию обычным способом end; end.
В результатевы п олнения окно п рог раммы п риметвид:
К ом м е н тар и и 1. П ринаж атиикноп ки« Создать п оток» б удутвы п олняться неодин, адва п отока: основной п оток п рилож ения об раб аты вает сооб щ ения, адресованны е г лавной ф орме, доп олнительны й – вы водит числа. Е с ли вы звать ф ункцию Func(nil) нап рямую (п ри наж атии кноп ки « Без п отока»), то все оп ерации б удет вы п олнять основной п оток, п оэтому п рог рамма« зависнет», п окане закончится цикл. В это время окно нереагируетнасоб ы тия, неп озволяя себ я нип ереместить, 6
низакры ть. П ринаж атиикноп ки« Создать п оток» окно п рог раммы б удет вести себ я об ы чны м, « друж елю б ны м» об разом. 2. Д ля вы вода строки текста вместо « нап раш ивавш ихся» визуальны х средств Delphi исп ользовалась ф ункция API TextOut. Д ело в том, что п одавляю щ ее б ольш инство визуальны х комп онентов Delphi стаб ильно раб отаю т только внутри г лавног о п отокап рилож ения. И склю чением являю тся комп оненты для доступ ак б азам данны х иг раф ические классы , раб отаю щ иесTCanvas (сп оследниминеоб ходимо ис п ользовать б локировкихолстаLock иUnLock [4]). Е слиж е б ез комп онентов Delphi внутридоп олнительны х п отоков об ойтись нельзя, то для создания таких п отоков рекомендуется исп ользовать сп ециализированны й клас с TThread, входящ ий в б иб лиотеку Delphi. 3. Класс TThread К лассTThread инкап сулирует ф ункции API п рог раммирования п отоков. Е г о основны мип реимущ ествами являю тся удоб ство исп ользования, свойственное всем клас сам-надстройкам, и наличие сп ециальног о методаSynchronize для корректног о исп ользования внутрип отоков визуальны х комп онентов VCL Delphi. С во йства и м ето ды класса TThread constructor Create Создаетп оток. Е слиарг ументимеетзначениеFalse, (CreateSuspensed: с озданны й п оток немедленно начинаетвы п олнение Boolean); (уп равлениеп ередается методу Execute) . Е слиTrue – п оток ож идаетвы зоваметодаResume destructor DeЗаверш аетп оток иосвоб ож даетвсерес урсы , им заstroy: override; няты е. В ы зы ваетс я автоматическип ризаверш ении методаExecute procedure Resume; В озоб новляетп оток п ослеп риостановки procedure Suspend; П риостанавливаетп оток property SusП ризап исиTrue/False п риостанавливаpended: Boolean; ет/возоб новляетп оток. П ричтениип оказы вает, не п риостановлен лип оток procedure TermiУс танавливаетсвойство Terminated в True. П риис nate; п ользованииэтог о методадля заверш ения п отока метод Execute долж ен вклю чать в с еб я п роверку с войстваTerminated (см. лаб . раб . № 2). property TermiП оказы ваетTrue, еслиранееб ы л вы зван метод Ternated: Boolean; minate. function WaitFor: П риостанавливаеттекущ ий п оток до заверш ения integer; заданног о п отокаивозвращ аеткод заверш ения. Н ап ример, внутрип отокаT1 вы зов code:=T2.WaitFor п риостанавливаетT1 до заверш ения T2 property Handle: Д ескрип тор п отока THandle; 7
property ThreadID: THandle; property Priority: TThreadPriority; procedure Synchronize (Method: TThreadMethod); procedure Execute; virtual; abstract; property ReturnValue: integer; property OnTerminate: TNotifyEvent;
И дентиф икатор п отока П риоритетп отока М етод исп ользуется для об ращ ения к комп онентам VCL внутрип отока. У казанны й в качествеарг ументаметод, содерж ащ ий вы зовы VCL, вклю чаетс яв г лавны й п оток п рилож ения. Главны й метод класса. О б язательно п ереоп ределяется, п ослечег о долж ен содерж ать код п отока К од заверш ения п отока. П о умолчанию – ноль. Д руг иезначения мог утб ы ть п рисвоены внутрип отокап о усмотрению п рог раммиста Соб ы тие, п роисходящ ееп ослезаверш ения метода Execute, но п еред Destroy
Прим е чан и я 1. Н еоб ходимы ми являю тся только методы Create и Execute. П оследний метод является аб страктны м. П оэтому нельзя создать экземп ляр TThread, необ ходимо п редварительно об язательно создать п отомкаклассаTThread ип ерекры ть в нем метод Execute, доб авив в нег о необ ходимую ф ункциональнос ть. 2. П риоритетп отока мож етп ринимать с ледую щ иезначения: tpIdle tpLowest tpLower tpNormal tpHigher tpHighest tpTimeCritical
П оток п олучаетквантвременитолько тог да, ког дасистеманаходится в состояниип ростоя П риоритетнадвап унктаниж енормальног о П риоритетнаодин п унктаниж енормальног о Н ормальны й п риоритет Н аодин п унктвы ш енормы Н адвап унктавы ш енормы М аксимальны й п риоритет
П риоритеты tpHighest иtpTimeCritical следуетназначать состорож ностью , чтоб ы ненаруш ить раб оту п рилож ения. Лаб о рато рн ая раб о та № 2 Раб отадемонстрируетметодику создания изаверш ения п отокаc п омощ ью методов классаTThread. О рг анизуйтенаф ормедвекноп ки иодну строку редактирования, зап иш ите об ъ явление классаTSimpleThread ип ереоп ределите ег о метод Execute, как это 8
п оказано налистинг е. В ф ормеоп ределитеметод OutMessage. В неш ний видраб отаю щ ег о п рилож ения п оказан нарисунке. unit ThrdUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} type // Объявление класса потока-потомка TSimpleThread = class(TThread) procedure Execute; override; public // Здесь удобно добавить любые поля и методы, //которые будут использоваться локально, внутри потока Count: Integer; // счетчик цикла procedure OutMessage; end; procedure TSimpleThread.Execute; begin // Содержание потока while not Terminated do begin//Поток будет выполняться, // пока не будет нажата кнопка Button2 Count := Count+1; Synchronize(OutMessage); // Безопасный вывод end; end; procedure TSimpleThread.OutMessage; begin Form1.Edit1.Text:=IntToStr(count); // Обращение к VCL end; var Thread1: TSimpleThread; // Экземпляр класса «поток» procedure TForm1.Button1Click(Sender: TObject); 9
begin Thread1:=TSimpleThread.Create(False);//Создание потока Thread1.Priority := tpLowest; // Приоритет Thread1.Count := 0; // Начальное значение счетчика end; procedure TForm1.Button2Click(Sender: TObject); begin Thread1.Terminate; // Завершаем бесконечный поток end; end.
Результатвы п олнения п рог раммы :
Ко м м ен тарии 1. А рг ументом методаSynchronize является имя м ет ода (н о н е пр оцеду р ы!), которы й об ращ ается к об ъ ектам VCL. П оследний метод долж ен б ы ть оф ормлен в видеп роцедуры б езарг ументов. Н ап ример, вы ш едля вы водав строку редактирования Edit1 б ы л оп ределен метод п отока procedure TSimpleThread.OutMessage; begin Form1.Edit1.Text := IntToStr(count); end;
авнутриметодаExecute п отокап роисходил вы зов Synchronize(OutMessage);
М етод Synchronize здесь необ ходим, чтоб ы во время зап ис ив об ъ ектEdit1 заб локировать г лавны й п оток п рилож ения: раб отаю щ ий г лавны й п оток п озволяет комп онентам, рас п олож енны м в окне, об мениватьс я сооб щ ениями; п риэтом мож етнас туп ить с итуация г онок, нап ример, одновременноеп рисваивание Form1.Edit1.Text := IntToStr(count);
10
иредактирование Edit1 друг им п отоком или п ользователем, что в данном п ростом п римеренеимеет особ ог о значения, но в п ринцип ен едопу ст и м о. Ч тоб ы лучш еп онять п роисходящ ее, изменитеметод, доб авив задерж ку на1 секунду: procedure TSimpleThread.OutMessage; begin Sleep(1000); Form1.Edit1.Text := IntToStr(count); end;
П ос ле зап ускап рог раммы об наруж ится, что в течение одной секунды меж ду п риращ ениямисчетчиканевозмож но ниотредактировать строку, нип ереместить окно: метод OutMessage вы п олняется в г лавном п отоке иб локирует ег о остальны едействия, как это б ы ло в лаб . раб оте1 п ринаж атиикноп ки« Безп отока». (В ременная задерж ка1 сек. нуж налиш ь, чтоб ы визуально заметить данны й эф ф ект). О чевидно, метод OutMessage нерекомендуетс я загромож дать вы числениями, так как это сильно замедлитраб оту г лавног о п отока. 2. Ч тоб ы создать п оток, удоб но вос п ользоваться имею щ имся в Delphi ш аб лоном: вы б рать п унктменю File | New | Thread Object иввестиимя классап отока-п отомкаTThread, нап ример, TFirstThread. П ослеэтог о п оявится автоматическисгенерированны й модуль соб ъ явлением классаTFirstThread, которы й следует долж ны м об разом видоизменить ип одклю чить к вы зы ваю щ ему модулю об ы чной п ользовадирективой uses. У пр а ж н ен и е: п еределайте лаб ораторную раб оту сис нием ш аб лонов. Лаб о рато рн ая раб о та № 3 (сам о сто ятельн ая) Д ораб отайте п реды дущ ий п роект, сделав дванезависимы х аналог ичны х п отокаThread1, Thread2, вы водящ их результаты в отдельны е строкиредактирования. Здесь мож но оп исать двакласса, но п оскольку двап отокаидентичны , аTSimpleThread. мож но ог раничиться созданием двух экземп ляров одног о класс Д ля ступ енчатой рег улировкип риоритетов ис п ользуйте двакомп онентаTTrackBar (см. рисунок). П роект долж ен п оказы вать изменение скоростираб оты в зависимостиотустановленног о п риоритета. О б разцы реш ения задачи с м. в [4,5].
11
4. С ин хро н изация п о то ко в К ак уж е уп оминалось, п ри доступ е п отоков к об щ им ресурсам (г лоб альны м данны м, одному итому ж е ф айлу, DLL, коммуникационному п орту ит.п .) возникаю т коллизии. П редотвратить коллизии мож но с п омощ ью различны х средств синхронизации. Ч ащ е вс ег о для этой цели ис п ользую тся: кр и т и чески е секци и , и склю ча ю щи е сем а ф ор ы (м ью т ексы), обычн ые сем а ф ор ы, событ и я. В с е уп омянуты емеханизмы основаны наб локировкедоступ ак ресурсу, п окаэтотресурсзаняткаким-либ о п отоком. Рассмотрим б олее п одроб но механизм критической секции, ог раничивш ись ег о реализацией наб азеф ункций API Win32 (как об ы чно, в Delphi имею тся аналог ичны е классы -надстройки). У часток кода, содерж ащ ий п отенциально оп асны е об ращ ения к ресурсу, п омечается как « критическая с екция». П еред входом в критическую с екцию п роверяется г лоб альная зап ись тип аTRTLCriticalSection (с труктуру зап исисм. в ф айле ..\borland\delphi4\source\rtl\win\windows.pas), в которой отмечено, вы п олняется ликритическая секция в данны й моментвремени каким-либ о друг им п отоком. Е слисекция незанята, п оток доп ускается к раб оте. В началекритической секциинеоб ходимо вы звать п одп рог рамму API procedure EnterCriticalSection (sect:TRTLCriticalSection);
которая п роверяетсостояниезап исиsect: TRTLCriticalSection и, еслив зап исисекция п омеченакак занятая друг им п отоком, п риостанавливаеттекущ ий п оток, п окакритическая секция неос воб одится. В концекритичес кой секциивы зы вается п одп рог рамма procedure LeaveCriticalSection (sect:TRTLCriticalSection);
которая делаетп ометку в зап иси, что критичес кая секция своб одна, идруг ой п оток в соответствиисп риоритетом п олучаетквантвремениивходитв критическую секцию . П редварительно п еред ис п ользованием необ ходимо п роинициализировать зап ись sect: TRTLCriticalSection сп омощ ью п роцедуры procedure InitializeCriticalSection(Sect); ап ризаверш енииисп ользования – удалить: procedure DeleteCriticalSection(Sect1); В рассматриваемом ниж еп римереп ервая оп ерация вы п олняется в об раб отчикес об ы тия создания ф ормы OnCreate, авторая – в об раб отчикесоб ы тия удаления ф ормы изп амятиOnDestroy. 12
Лаб о рато рн ая раб о та № 4. Синхронизация доступ ак г лоб альной п еременной сп омощ ью критической секции Рассмотрим п ример, ког дадвап отокаоб ращ аю тся к одной итой ж е г лоб альной п еременной GlobalData, увеличиваю тисразу уменьш аю теезначение GlobalData := GlobalData+3; GlobalData := GlobalData-3;
арезультаты вы водят в соответствую щ ие комп оненты TMemo. Д ля созданиеп рог раммы вы п олнитес ледую щ ее. 1. Разместитенаф ормедвакомп онентаMemo1 иMemo2, двеметкиснадп исями « П ервы й п оток:» и « В торой п оток:», кноп ку Button1 « В ы п олнить», вы клю чатель cbSect: TCheckBox сп одп исью « И сп ользовать критическую секцию ». Ч тоб ы мож но б ы ло сравнивать результаты , п олученны е сисп ользованием синхронизациииб езсинхронизации, в об раб отчикесоб ы тия OnClick для вы клю чателя зап иш ите CritSect := cbSect.Checked;
2. И нициализацию и удаление критичес кой секции зап иш ите, с оответственно, в об раб отчиках соб ы тий OnCreate иOnDestroy для ф ормы . 3. Т ак об ап отокаидентичны , нерационально создавать дваотдельны х класса. П оэтому оп иш итеодин классTMyThread, п ереоп ределитеег о методы и создайтедваэкземп ляраэтог о класса, как п оказано налистинг е. unit ThrdUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Button1: TButton; cbSect: TCheckBox; Label1: TLabel; Label2: TLabel; Memo1: TMemo; Memo2: TMemo; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure cbSectClick(Sender: TObject); private { Private declarations } public { Public declarations } end; 13
var Form1: TForm1; type TMyThread = class(TThread) private { Private declarations } mem: TMemo; // В переменную mem при вызове конструктора потока будет // передаваться конкретный экземпляр TMemo protected constructor Create (M: TMemo);// Переопределение procedure Execute; override; procedure OutMessage; end; implementation {$R *.DFM} var CritSect: boolean; // Флаг «включать-не включать» Sect1: TRTLCriticalSection; //Критическая секция GlobalData: integer; // Глобальная переменная constructor TMyThread.Create(m: TMemo); begin //Переопределяем конструктор Inherited Create(False);//Вызываем унаследованный Mem := m; // Передаем, куда записывать числа end; procedure TMyThread.OutMessage; begin // Добавление строки в редактор Mem.Lines.add(IntToStr(GlobalData)); end; procedure TMyThread.Execute; var j: integer; begin for j:=1 to 50 do begin // Если механизм критической секции используется if (CritSect) then EnterCriticalSection(Sect1); // Вход в критическую секцию // Изменение глобальной переменной GlobalData := GlobalData+3; Sleep(3); // Задержка на 3 мс для увеличения // вероятности рассинхронизации GlobalData := GlobalData-3; Synchronize(OutMessage); // Выход из критической секции if (CritSect) then LeaveCriticalSection(Sect1); end; end;
14
var Thread1, Thread2: TMyThread; //Экземпляры потоков procedure TForm1.Button1Click(Sender: TObject); begin GlobalData := 100; Memo1.Lines.Clear; Memo2.Lines.Clear; Thread1 := TMyThread.Create(Memo1);// Старт потока 1 Thread2 := TMyThread.Create(Memo2);// Старт потока 2 end; procedure TForm1.FormCreate(Sender: TObject); begin InitializeCriticalSection(Sect1); CritSect := false; end; procedure TForm1.FormDestroy(Sender: TObject); begin DeleteCriticalSection(Sect1); end; procedure TForm1.cbSectClick(Sender: TObject); begin CritSect := cbSect.Checked; end; end.
О чевидны й, казалось б ы , результат раб оты п отоков (GlobalData=100) искаж ается коллизией « г онок». О кно п рог раммы б езисп ользования синхронизации имеетвид:
И сп ользованиекритичес кой секцииреш аетп роб лему: 15
В заклю чениекратко охарактеризуем некоторы едруг иеметоды синхронизации. Семаф оры рег улирую тчисло п отоков, которы емог утисп ользовать ресурс. И склю ча ю щи й сем а ф ор (mutex, м ью т екс) доп ускаетк ресурс у только один п оток, обычн ые сем а ф ор ы доп ускаю т конечное число п отоков. Семаф оры имью тексы во мног ом п охож инакритическиесекции, методикаих исп ользования п рактическип олностью совп адаетсметодикой, рассмотренной вы ш е. П реимущ еством п о сравнению скритическимисекциямиявляется, п реж де всег о, г лоб альность действия, т.е. сп ос об ность б локировать п отоки, зап ущ енны е всемиактивны мип рилож ениями. К рометог о, п риоб ращ ениик семаф орам имью тексам мож но указы вать максимальное время ож идания доступ ак ресурсу, что п озволяет п редотвращ ать ситуацию « туп иков». М ьюте кс создается ф ункцией function CreateMutex( Attr: Pointer; // flag: Boolean; // lpName: PChar // ): THandle; //
указатель на атрибуты безопасности флаг создания указатель на имя мьютекса дескриптор мьютекса
Стандартны й вариантс оздания: hMutex := CreateMutex(Nil, False, Nil);
М ью тексы мог утнаходиться в сиг нальном (еслиим невладеетниодин п оток, т.е. ресурссвоб оден) или несиг нальном состоянии (п оток владеет мью тексом). Ч тоб ы п оток завладел мью тексом (т.е. п олучил доступ к ресурсу), необ ходимо вы звать ф ункцию ож идания function WaitForSingleObject( hHandle: THandle; // дескриптор мьютекса dwMilliseconds: DWord // время ожидания в мс ): DWord; 16
П араметр dwMilliseconds мож етп ринимать значениеInfinite, что означает б есконечны й интервал ож идания. Ф ункция заверш ает раб оту, еслимью тексстановится сиг нальны м илиистекло время ож идания. П ос леэтог о п оток, находивш ийся в состоянииож идания мью текса, п олучаетк нему дос туп , амью текс, п олучивш ий новог о владельца, п ерестаетсиг нализировать. М ью тексмож но с равнить с« эстаф етной п алочкой», которую б ег ун (п оток) молчадерж ит, п роходя дистанцию , икричит« Д ерж и!» (сиг нализирует), заверш ив дистанцию . П ос ле тог о, как п оток вы п олнил участок кода, содерж ащ ий совместно исп ользуемы й ресурс, необ ходимо освоб одить мью тексот п отока-владельцасп омощ ью ф ункцииAPI function ReleaseMutex( hHandle: THandle; // дескриптор мьютекса ): Boolean;
П ризаверш ениираб оты мью тексудаляется изп амятисп омощ ью известной В ам ф ункцииCloseHandle, в которую п ередается дескрип тор мью текса. С е м афор с оздается ф ункцией function CreateSemaphore ( Attr: Pointer; // указатель на атрибуты безопасности InitialCount: longint; // Начальное число потоков, // допущенных к объекту MaxCount: longint; // Максимальное число допускаемых // потоков lpName: PChar // указатель на имя семафора ): THandle; // дескриптор семафора
Семаф ор сиг нализирует, еслиInitialCount б ольш енуля, инеп одаетсиг нала, еслиInitialCount равен нулю . Д ля доступ а к об ъ екту исп ользуется ф ункция ож идания WaitForSingleObject или WaitForMultipleObjects [6]. П ризаверш ении ф ункции ож идания значение с четчикаInitialCount соответственно уменьш ается ип оток п олучаетдоступ к ресурс у. П ризаверш ениидоступ ак ресурс у необ ходимо вы звать ф ункцию , увеличиваю щ ую значениесчетчикасемаф ора: function ReleaseSemaphore( hHandle: THandle; // дескриптор семафора ReleaseCount: longint // приращение счетчика LP: Pointer // как правило, nil ): Boolean;
Болееп одроб ная инф ормация п риведенав [6]. Упр аж н е н ие : П еределайте лаб ораторную раб оту № 4, заменив критическиесекцииа) мью тексами, б ) семаф орами. 17
Задан ия для сам о сто ятельн о й раб о ты 1. Создать двап отока, один изкоторы х зап олняетMemo случайны мичислами до остановки п роцесс ап ользователем, авторой осущ ествляет вы числение очередног о числаФ иб оначчип осле наж атия п ользователем кноп ки. П рип ревы ш ениидоп устимой г раницы вы числения целог о числаизменить надп ись накноп кеип ерейтик вы числению квадратног о корня. 2. Создать двап отока, один изкоторы х вы водитв Memo 200 строк, зап олняя их соответствую щ иминомеру строкичис лами, авторой вы числяет значение ф ункциив точке. В ы б ор ф ункцииреализовать сп омощ ью ComboBox, азначение арг ументавводить в редакторе. Д ля зап олнения Memo п редусмотреть индикатор п роцес са. 3. В ы числить п риб лиж енное значение оп ределенног о интег раласп омощ ью методап рямоуг ольника, методатрап еций, методаСимп сона. В ы б ор ф ункцииреализовать сп омощ ью ComboBox, аг раницы отрезказадавать в редакторе. П редусмотреть возмож ность г раф ическог о отоб раж ения. 4. В ы числить п риб лиж енное значение оп ределенног о интег раласп омощ ью методатрап еций. Разны е п отоки осущ ествляю т вы числения сразличны м ш агом. В ы б ор ф ункцииреализовать сп омощ ью ComboBox, аг раницы отрезказадавать в редакторе. П редусмотреть возмож ность г раф ичес ког о отоб раж ения. 5. Реализовать реш ение задачиК ош идля об ы кновенны х диф ф еренциальны х уравнений методами Э йлераиРунг е-К утта. П редусмотреть индикатор п роцессав видекруг овой диаграммы . 6. Реш ить нелинейноеуравнениесодним неизвестны м методамип оловинног о деления, методом хорд, методом Н ью тона. П редусмотреть возмож ность г раф ическог о отоб раж ения. 7. П ользователь задает 2 ф ункции. Реализовать п отоки для п ос троения г раф иков ф ункций п о задаваемому числу точек свозмож ностью задания п риоритетап отока. Т очкип ересечения вы делить друг им цветом. 8. Задан мас сив целы х п олож ительны х чисел. О сущ ес твить сортировку массиваметодамип узы рька, вы б оркииметодом б ы строй с ортировки. Д ля каж дог о методап редусмотреть возмож ность г раф ическог о отоб раж ения: каж дому числу массивап оставить в соответствие линию п роп орциональной длины ; п ри сортировкелиниитакж еменяю тся местами. 9. Задается ф ункция. В нескольких окнах п остроить г раф икиф ункциип о задаваемому числу точек свозмож ностью задания п риоритетап отока. 10. О п исать движ ение ш арикав п рямоуг ольной об ластисотраж ением от г раниц п од случайны м уг лом. П редусмотреть возмож ность зап усканескольких ш ариков. 11. Реализовать алг оритм нахож дения кратчайш ег о п ути в г раф е. Создавать п отокип ривы ходеизрас сматриваемой верш ины нескольких дуг . 12. Заш иф ровать текст п о ф ормуле yi=xi+ki mod n, атакж е методом п ерестановкисзаданием двух клю чей. 13. П риб лизительно вы числить значениеинтег рала
18
0 ,976
0 ,146 t ∫ [ 1 /( 1 + t ) + ( 1 + t ) − e − cos( t )] dt
− 0 ,82
как сумму соответствую щ их с теп енны х рядов, задавая ог раничения навеличину n членарядадля каж дог о п отокаотдельно. 14. И зоб разить наф орме несколько ф иг ур, вращ аю щ ихся сразличны ми скоростями. 15. Рассчитать сиг налы навы ходе авторег рессионны х моделей различны х п орядков, изоб раж ая г раф икинаразличны х PaintBox. 16. Рассчитать реакцииФ Н Ч Баттервортаn-г о п орядканаб елы й ш ум. Литература 1. К астер Х . О сновы Windows NT иNTFS. – М .: И здательский отдел « Русская редакция» Т О О « Channel Trading Ltd», 1996. – 440 с. 2. К инг А . Windows 95 изнутри. – СП б : П итер, 1995. – 512 с. 3. К алвертЧ . Delphi 4. Самоучитель. – К .: И зд-во « Д иас оф т»,1999. – 192с. 4. Д арахвелидзеП .Г., М арков Е .П . Delphi 4. – СП б .: БХ В -Санкт-П етерб ург , 1999. – 816 с. 5. А лександровский А .Д . Delphi 5.0. Разраб откакорп оративны х п рилож ений. – М .: Д М К , 2000. – 512 с. 6. Бартеньев О .В . Visual Fortran: новы евозмож ности. - М .: « Д иалог – М И Ф И », 1999. - 304 с. 7. В ведениев Delphi / Сос т. :Рудалев В .Г., К ремер А .И .; В оронеж . г ос . ун-т. - В оронеж , 2000. – 36 с.
Составители: Рудалев В алерий Геннадьевич, К ры ж ановс кая Ю лианаА лександровна Редактор Т ихомироваО .А .
19