Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Поток_1 Поток_2






       
   


ждать mutex A ждать mutex A,

и mutex B mutex B

 

Допустим, поток_3 освободил mutex A. Тогда ОС передает права на него потоку_1. Затем 3-й поток освободит mutex B.

Система передает права на него потоку_2.

Теперь поток_1 и поток_2 друг друга – 1-й владеет mutex’ом A, но не может выполнятся и освободить его, поток_2 никогда не освододит mutex A. Поток_2 – владеет B, но никогда не освободит его.

Это пример тупика двух процессов.

Для борьбы с тупиками функция WaitForMultipleObjects никогда не восстанавливает занятое состояние объектов, пока все из числа указанных объектов не освободятся.

 

Применение Обектов mutex вместо критических критических секций.

Вместо критических секции используется Mutex.

1) создать mutex

HM: =CreateMutex(nil, False, nil);

2) создать поток

Th1: =CreateTHread(nil, ….);

Th2: = CreateTHread(nil, …);

Перед критическим участком каждого потока вызвать функцию

WaitForSingleObject (HM, Infinite) (если HM свободен, он переводится в занятое состояние, а поток входит в критический участок). В конце критического участка необходимо перевести mutex в свободное состояние.

ReleaseMutex (Hmutex): boolean; Эта функция переводит объект mutex из занятого состояния в свободное (аналогично LeaveCriticalSection).

Функция ReleaseMutex воздействует на mutex, только если поток, вызвавший ее, владеет этим объектом.

 

Отказ от объекта mutex

Объект mutex отличается от других синхронизирующих объектов ядра тем, что вызвавшему его потоку передаются права на владения им. Другие синхронизирующие объекты могут быть либо свободны, либо заняты. А объекты mutex способны еще и запомнить, какому потоку они принадлежат.

В случае аварийного завершения потока, владеющего объектом Mutex, Mutex никогда не освободить, так как никакой другой поток не сможет освободить его вызовом функции RealeseMutex. ОС не терпит подобных ситуаций и переводит mutex в свободное состояние (для предотвращения блокировки оставшихся потоков). Это действие называется отказ от мьютекса.

С объектами mutex связан счетчик числа их владельцев. Поэтому, если поток вызывает WaitForSingleObject для того объекта mutex, который уже принадлежит ему, он сразу получит доступ к защищенным данным (благодаря счетчику система определяет, что поток уже владеет объектом mutex). При каждом вызове WaitForSingleObject потоком – владельцем объекта mutex – этот счетчик увеличивается на 1. Поэтому для освобождения mutex потоку придется соответствующее число раз вызывать функцию RealeseMutex.

Семафоры

Объекты ядра “семафор” используются для учета ресурсов. При запросе у семафора ресурса ОС проверяет, свободен ли данный ресурс, и если свободен, уменьшает счетчик доступных ресурсов, не давая вмешиваться другому потоку. Только после этого система разрешает другому потоку запрашивать какой-либо ресурс. Например, у ПК установлено три последовательных порта, значит одновременно или могут воспользоваться не более чем три потока (порт может быть закреплен за одним потоком). Для выделения портов необходимо создать семафор со счетчиком, равным 3. Семафор считается свободным, если его счетчик ресурсов больше 0, и занятым, если счетчик равен 0. При каждом вызове из потока функции WaitForSingleObject с передачей ей описателя семафора система проверяет, больше ли нуля счетчик ресурсов у данного семафора. Если да, то счетчик ресурсов уменьшается на 1, выполнение потока продолжается. Если счетчик ресурсов=0, поток должен ждать освобождения ресурса.

В отличие от mutex, семафоры не передаются во владение какому-либо потоку.

Семафор создается функцией

CreateSemafore (nil //атрибуты, InitSem, MaxSem //integer, LpszSemName // Имя семафора для ссылок на семафор из других процессов): Thandle;

Для случая использования 3 портов семафор создается функцией

Hs: = CreateSemafore (nil, 3, 3, ‘’);

.– все 3 порты свободны.

Освобождение семафора – увеличение счетчика ресурсов – выполняет функция

ReleaseSemafore (HandleSem, CRelease //количество возвращаемых ресурсов, lpPrevios): boolean;

Последний параметр – указывает на переменную integer, в которую заносится значение счетчика ресурсов, предшествовавшему тому, что получается после увеличения его на CRelease. Можно передавать nil.

Получить содержимое счетчика семафора, не измерив его значения, нельзя.

 

Решение задачи поставщик – потребитель с помощью операций P(S) и V(S)

InitSem (Sсв, N)

InitSem (Sзап, 0)

InitSem (Sвз, 1)

Поставщик: WhileTrue do

Begin

Создать сообщение

P(Sсв)

P(Sвз)

Послать сообщение

V(Sсв)

V(Sвз)

End.

Потребитель: WhileTrue do

Begin

Создать сообщение

P(Sзап)

P(Sвз)

Послать сообщение

V(Sсв)

V(Sвз)

End.

Семафоры Sсв, Sзап используется как счетчики свободных и занятых буферов т.е. являются общими переменными для обоих потоков. Поэтому они должны быть защищены двоичным семафором Sвз. Если поставщик проверил P(Sсв) и находится на семафоре Sсв=0, он блокируется на нем. Если потребитель проверил P(Sзап) и находит при этом Sзап.=0, он блокируется на семафоре Sзап.

2 семафора предназначен для возможности блокировки 2 потоков. 3-й семафор Sвз обеспечивает неделимость операций.

.

События - Event.

Самые примитивные средства синхронизации – только оповещают об окончании какой-либо операции. Используются два типа объектов “события”:

· событие со сбросом вручную (manual-reset-events);

· событие с автоматическим сбросом (auto-reset-events).

Типичная схема использования событий – 1 поток выполняет некоторую подготовительную операцию (например, считывание данных из файла в буфер), а затем сигнализирует другому потоку (или нескольким потокам), что они могут продолжить работу (например, обработать считанные данные).

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.