Тема 2.9 Создание многопоточных приложений



    1. Понятие потоков и процессов.

    2. Средства синхронизации потоков.

    3. Создание модулей-потоков в Delphi.

    4. Свойства и методы потоков.

    Понятие потоков и процессов

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

    Потоки позволяют в рамках одной программы решать несколько различных задач одновременно.

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

    Кванты выделяются не программам и процессам, а порожденным этими процессами потокам. Каждый процесс состоит минимум из одного потока. Сегодня все современные операционные системы позволяют запускать в рамках одного процесса несколько различных потоков.

    Преимущество использования потоков:

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

    2. Дополнительные возможности управления приложением за счет управления приоритетами потоков.

    3. Возможность снять проблему возрастания "нагрузки" на приложение, увеличением количества потоков.

    Ассиметричные потоки - решающие различные задачи и не разделяющие совместные ресурсы. Необходимость в ассиметричных потоках возникает в следующих случаях:

    - когда в программе необходимы длительные вычисления, при этом сохраняя нормальную реакцию на ввод;

    - при необходимости обработки асинхронного ввода/вывода с использованием различных устройств;

    - если необходимо создать несколько окон и одновременно обрабатывать ввод в них данных.

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

    Тупики имеют место, когда один поток ожидает ресурс, который в данный момент принадлежит другому потоку. Например, поток 1 захватить ресурс А, и для продолжении работы, ждет возможности захватить ресурс В. В то же время второй поток - Поток 2 захватывает ресурс В и ждет возможности захватить ресурс А. В результате этого сценария заблокируется оба потока; ни один из них не будет исполняться. Такими ресурсами могут выступать любые совместно используемые объекты системы - файлы, область памяти, внешние устройства.

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

    Для разрешения ситуаций гонок и тупиков можно использовать некоторые приемы. 

        

Средства синхронизации потоков

    Возможными вариантами решения проблемами является 4 объекта, которые разработаны специально для синхронизации. Это такие объекты как событие, взаимное исключение, семофор и таймер.

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

    Событие - простейший выбор для задач синхронизации. Класс TEvent (событие) имеет два важных метода: setEvent - перевод объекта в активное состояние и ResetEvent-  перевод в пассивное состояние.

Конструктор события имеет следующий вид:

    constructor Create (Event Attributes: PSecurity Attributes; ManualReset, InitialState: Booiean; const Name: string);

    где параметр initialstate- начальное состояние объекта,

ManualReset- способ его перевода в пассивное состояние. Если этот параметр равен True, событие должно быть переведено в пассивное состояние вручную. Иначе событие сбрасывается по мере того, как стартует хоть один поток, ждавший данный объект.

    Взаимное исключение позволяет владеть ресурсом в данное время одному из потоков. Класс, инкапсулирующий взаимное исключение TMutex.

Конструктор: constructor Create(const Name: string); задает имя создаваемого объекта. Первоначально объект не принадлежит никому.

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

    В Delphi можно использовать также объект типа критическая секция.

Критические секции подобны взаимным исключениям, однако ,между ними существуют два главных отличия:

    - взаимные исключения в отличие от критических секций могут быть                      

      совместно использованы потоками в различных процессах;

    - если критическая секция принадлежит другому потоку, ожидающий    

      поток блокируется вплоть до освобождения критической секции. В   

      отличие от этого, взаимное исключение разрешает продолжение по  

      истечении тайм-аута.

      Критические секции и взаимные исключения очень схожи. На первый взгляд, выигрыш от использования критической секции вместо взаимного исключения не очевиден. Критические секции более эффективны , чем взаимные исключения, т.к. используют меньше системных ресурсов. Критическая секция всегда ждет столько времени, сколько потребуется; взаимные исключения же могут быть установлены на определенный интервал времени, по истечении которого выполнение продолжается.

    Создание модулей потоков в Delphi

        Для создания дополнительного потока в программах Delphi предназначен специальный модуль - Thread Object. Для его создания используется команда File -> New. При выборе этого модуля Delphi запрашивает имя класса, который будет дочерним для основополагающего класса TThread. Необходимость наследования связана с тем, что класс TThread содержит абстрактный метод Execute, который обязан перекрываться в потомках.

  Файл модуля-потока имеет следующую структуру:

  unit Unit2;

  interface

uses

  Classes;

type

MyThread = class(TThread)

private

Private declarations

protected

procedure Execute; override;

end;

implementatoin

procedure MyThread. Execute;

begin

 Place thread code here

end;

end.

    Программирование потока имеет важное отличие от обычной программы - поток не может использовать методы и свойства визуальных компонентов, которые приводят к изменению внешнего вида программы. Для этого поток обращается к специальному методу Synchronize, с помощью которого осуществляется синхронизация исполнения главного потока с дополнительным. Единственным параметром обращения к этому методу должно быть имя любой процедуры без параметров. Внутри такой процедуры допустимо обращение к методам и свойствам визуальных компонентов.

Свойства и методы потоков

1. Procedure Execute; virtual; abstract; - код, исполняемый в создаваемом потоке TThread.

2. property Terminated: Boolean; -это указание потоку завершиться с возможностью корректно освободить ресурсы.

3. Метод WaitFor  предназначен для синхронизации и позволяет одному потоку дождаться момента, когда завершится другой поток.

4. Свойство Priority позволяет запросить и установить приоритет потоков. Допустимыми значениями приоритета для объектов TThread являются такие значения tridle, tpLowest, tpLower, tpNormai, tpHigher, tpHignest и tpTimeCritical.

5. procedure Synchronize (Method; TThreadMethod); Этот метод относится к секции protected, т.е. может быть вызван только из потомков TThread, Delphi  предоставляет метод Synchronize для безопасного вызова методов VCL внутри потоков. Во избежание конфликтных ситуаций , метод Synchronize дает гарантию, что к каждому объекту VCL одновременно имеет доступ только один поток. Аргумент, передаваемый в метод Synchronize,- это имя метода, который производит обращение к VCL;вызов Synchronize с этим параметром -это то же, что и вызов самого метода.

6. procedure Suspend;

7. Вызов метода Suspend приостанавливает поток, сохраняя возможностью повторного запуска. Метод Suspend приостанавливает поток вне зависимости от кода, который исполняется потоком в данный момент; выполнение продолжается с точки останова.

8. Свойство Suspend позволяет программисту определить, не приостановлен ли поток.

Свойство ReturnValue позволяет узнать и установить значение, возвращаемое потоком его завершении.

 


Дата добавления: 2018-04-05; просмотров: 422; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!