Мегаобучалка Главная | О нас | Обратная связь


Многопоточные приложения



2020-02-03 166 Обсуждений (0)
Многопоточные приложения 0.00 из 5.00 0 оценок




Потоки - это объекты, получающие время процессора. Потоки позволяют в рамках одной программы решать несколько задач одновременно. Операционная система предоставляет приложению некоторый интервал времени центрального процессора (называемый квантом) и в момент, когда приложение переходит к ожиданию сообщений или освобождает процессор, ОС передает управление другой задаче. Планируя время центрального процессора, Windows распределяет его межу потоками, а не между приложениями. Время процессора выделяется квантами (около 19 мс). Чтобы использовать все возможности операционной системы, программист должен знать, как создавать потоки.

Существует два типа потоков: асимметричные и симметричные.

Асимметричные потоки (asymmetric threads) решают различные задачи, и, как правило, не разделяют совместные ресурсы.

Симметричные потоки (symmetric threads) выполняют одну и ту же работу, разделяет одни и те же ресурсы и исполняют один код. Пример приложения с симметричными потоками - электронные доски объявлений (Bulletin Board Systems, BBS). Для обслуживания каждого дозвонившегося туда пользователя BBS запускает новый поток.

Программа в терминах операционной системы представляет собой процесс. Процесс - это совокупность виртуальной памяти, исполняемого кода, потоков и данных. Процесс должен содержать по крайней мере один поток.

Если задачи приложения можно органично разделить на различные подмножества: обработка событий, ввод-вывод, связь и т.д., то потоки могут быть органично встроены в программное решение. Сделав приложение многопоточным, программист получает дополнительные возможности управления им. Например, через управление приоритетами потоков. Другое важное преимущество использования потоков - при возрастании "нагрузки" на приложение можно увеличить их количество и можно увеличить их количество, и, тем самым, снять проблему.

Две типичные проблемы, с которыми может столкнуться программист при работе с потоками - это ситуации тупиков и гонок.

Гонки

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

Тупики

Тупики имеют место, когда поток ожидает ресурс, который в данный момент принадлежит другому потоку. ассмотрим пример: поток 1 захватывает объект А и, для того, чтобы продолжать работу, ждет возможности захватить объект Б. В то же время, поток 2 захватывает объект Б и ждет возможности захватить объект А. В результате оба потока оказываются заблокированными - ни один из них не будет выполняться. Для исключения ситуаций тупиков и гонок потоки следует синхронизировать.

Приоритеты потоков

Операционная система планирует время в соответствии с приоритетами потоков. Когда поток создается, ему назначается приоритет, соответствующий приоритету породившего его процесса. Процессы, в свою очередь, имеют следующие классы приоритетов:

1. Pеального времени (Real Time). Этот класс определяет приоритет даже больший, чем у многих процессов операционной системы. Такой процесс необходим для процессов, обрабатывающих высокоскоростные потоки данных.

2. Высокий (High). Этот класс определяет приоритет выше нормального. Он используется процессами, которые должны завершиться за короткое время.

3. Нормальный (Normal). Большинство процессов запускается в рамках этого класса.

4. Фоновый (Idle). Процессы с таким приоритетом запускаются только в случае, если в очереди диспетчера задач нет других процессов. Программисты могут использовать этот класс приоритетов для организации фоновых процедур и реорганизации данных. Примером может служить проверка орфографии и сохранение файла в MS Word.

Приоритеты имеют значения от 0 до 31. Приоритет потока может отличаться от приоритета породившего его процесса на плюс-минус две единицы. Соответствующие величины показаны ниже.

Низший
Пониженный
Нормальный
Повышенный
Высший

Фоновый

2
3
4
5
6

Нормальный заднего плана

5
6
7
8
9

Нормальный переднего плана

7
8
9
10
11

Высокий

11
12
13
14
15

Реального времени

22
23
24
25
26

Класс tThread

Нужно отдавать себе отчет, что с точки зрения операционной системы, поток - это ее объект. При создании он получает дескриптор и отслеживается ОС. Объект класса tThread - это конструкция Delphi, соответствующая потоку ОС.

Для создания потока служит конструктор

Constructor Create(CreateSuspended:Boolean);

Если параметр CreateSuspended равен TRUE, вновь созданный поток не начинает выполняться до тех пор, пока не будет вызван метод Resume. В противном случае сразу после создания поток начинает исполнение.

Метод Procedure Resume;

класса tThread вызывается, когда поток возобновляется после остановки, или если он был создан конструктором с параметром CreateSuspended, равным TRUE.

Вызов метода

Procedure Suspend;

Приостанавливает поток с возможностью повторного запуска в последствии. Выполнение продолжается с точки останова.

Свойство Property Suspended:boolean;

Позволяет программисту определить, не приостановлен ли поток. С помощью этого свойства можно также запускать и останавливать поток.

Для окончательного завершения потока (без последующего запуска) существует метод

procedure Terminate;

он останавливает поток и возвращает управление вызвавшему его процессу только после того, как это произошло. Свойство

property Terminated:boolean;

позволяет узнать, вызывался ли уже метод Terminate.

Метод Function WaitFor: integer;

Предназначен для синхронизации и позволяет одному потоку дождаться момента, когда завершится другой. Если внутри потока FirstThread написать код:

Code:=SecondThread.WaitFor;

то это означает, что поток FirstThread останавливается до завершения потока SecondThread . Метод WaitFor возвращает значение свойства ReturnValue.

Свойство Property Priority: tThreadPriority;

Определяет приоритет потока. Допустимыми значениями приоритета являются: tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritrcal.

Метод Procedure Synchronyze(Method: tTHreadMethod);

предназначен для безопасного вызова методов VCL внутри потоков. Этот метод гарантирует, что к каждому объекту VCL одновременно имеет доступ только один поток, что позволяет избежать ситуации гонок. Аргумент, передаваемый в метод Synchronyze - это имя метода, который производит обращение к VCL. Вызов Synchronyze с таким аргументом, это то же самое, что и вызов самого метода. Synchronyze находится в области видимости protected, и, следовательно, доступен только в методах потомков класса tThread.

Главным методом класса tThread является абстрактный метод

Procedure Execute; virtual; abstract;

Этот метод должен быть переопределен в классе-потомке tThread. В его теле должен содержаться код, который и представляет собой собственно поток. Если поток был создан с аргументом CreateSuspended, равным FALSE, то метод Execute вызывается сразу после создания потока; в противном случае - после вызова метода Resume.

Если поток рассчитан на однократное выполнение каких либо действий, то никакого специального кода завершения для него писать не нужно. После выполнения метода Execute будет вызван деструктор, который сделает все необходимое.

Если же в потоке будет выполняться бесконечный цикл, и поток должен завершиться вместе с приложением, то условия окончания цикла должны быть примерно такими:

rocedure tMyThread.Execute;
Begin
Repeat
// Код потока
Until CancelCondition or Terminated;
End;

Здесь CancelCondition - ваше личное условие завершения потока, а свойство Terminated говорит о завершении потока извне (скорее всего, завершился породивший его процесс).

С завершением потока нужно быть очень внимательным: если он зациклился, зависнет все приложение.

Свойство Property ReturnValue: Integer;

Позволяет узнать код завершения потока. Эта величина полностью определяется пользователем.

Для создания своего потока следует найти в репозитории значок Thread Object (он находится на странице New). Двойной щелчок на этом значке вызовет диалоговое окно New Thread Object, в которое следует ввести имя будущего класса-потомка tThread. Нажатие кнопки ОК вызовет генерацию шаблона нового потока:

unit ThreadUnit;
interface
uses Classes;

type
tMyThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;

implementation

{ Important: Methods and properties of objects in VCL can only be used in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure tMyThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ tMyThread }

procedure tMyThread.Execute;
begin
{ Place thread code here }
end;

end.



2020-02-03 166 Обсуждений (0)
Многопоточные приложения 0.00 из 5.00 0 оценок









Обсуждение в статье: Многопоточные приложения

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Почему люди поддаются рекламе?: Только не надо искать ответы в качестве или количестве рекламы...
Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (166)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.01 сек.)