Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
25
Добавлен:
17.04.2013
Размер:
99.33 Кб
Скачать

12

СПО Лекция 8[28.02.17]

Лекция 8. Типовые задачи синхронизации. Примитивы синхронизации в Win32 api

  • Типовые задачи синхронизации

  • Критическая секция

  • Атомарные операции

  • Объекты ядра Win32 API

Типовые задачи синхронизации

Задача о производителе и потребителе

Моделирует взаимодействие (обмен данными) между двумя процессами: один пишет в буфер, а другой читает из буфера.

Ограничения:

  • «Производитель» должен ждать, если буфер полон.

  • «Потребитель» должен ждать, если буфер пуст.

  • Запись и чтение из буфера – критическая секция.

Задача о читателях и писателях

Моделирует обращение процессов к базе данных. «Читатели» не модифицирую базу данных и могут читать одновременно, если никто не пишет. «Писатель» модифицирует базу данных и может это делать только если никто не пишет и никто не читает.

Ограничения:

  • «Читатель» должен ждать, пока кто-то пишет.

  • «Писатель» должен ждать, пока кто-то пишет или кто-то читает.

  • Модификация переменных состояния (счетчик читающих и т.п.) должно выполняться в критической секции.

Задача о Читателях и Писателях

Эта одна из модельных задач синхронизации, описывающих доступ процессов к разделяемой базе данных.

Процессы подразделяются на две категории:

  • Читатели никогда не модифицирую базу данных

  • Писатели читают и модифицируют базу данных

Правила игры таковы:

  • Читатели могут работать параллельно, если никто из писателей не модифицирует базу данных

  • Модифицировать базу может только один писатель и когда никто не читает из базы данных

  • Переменные состояния может просматривать и менять только один процесс

Схема решения

Читатель:

Ждать пока закончит работу писатель (если кто-то пишет)

Читать из базы данных

При необходимости разбудить ожидающего писателя

Писатель:

Ждать пока закончат работу все читатели (если кто-то читает)

Модифицировать базу данных

При необходимости разбудить ожидающих читателей

Переменные состояния:

AR – число активных (читающих из БД в данное время) читателей

AW – число активных писателей

WR – число ждущих читателей

WW – число ждущих писателей

Условные переменные:

ok_to_read – NULL

ok_to_write – NULL

lock - free

Решение

Reader() {

lock.Acquire();

while((AW+WW)>0) {

WR++; ok_to_read->Wait(&lock); WR--;

}

AR++;

lock.Release();

//======================

ACCESS DB

//======================

lock.Acquire();

AR--;

if( AR==0 && WW>0)

ok_to_write->Signal(&lock);

lock.Release();

}

Writer() {

lock.Acquire();

while((AW+AR)>0) {

WW++; ok_to_write->Wait(&lock); WW--;

}

AW++;

lock.Release();

//======================

ACCESS DB

//======================

lock.Acquire();

AW--;

if( WW>0)

ok_to_write->Signal(&lock);

else

ok_to_read->Broadcast(&lock);

lock.Release();

}

Вопросы:

Возможно ли бесконечное откладывание читателей? (Да)

Зачем нужен while у читателя?

Задача об обедающих философах

Моделирует использование общих ресурсов несколькими процессами. Суть задачи такова. Пять философов сидят за круглым столом. На столе 5 тарелок с макаронами и 5 вилок по одной между тарелками. Предполагается, что есть надо двумя вилками сразу. Поведение каждого из философов таково: Думает – Хочет есть (пытается взять две вилки) – Ест.

Ограничения:

  • Философ должен ждать, пока не освободятся две вилки рядом с ним.

  • Модификация переменных состояния должно выполняться в критической секции.

Задача о спящем парикмахере

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

Ограничения:

  • Клиент должен ждать если есть очередь или парикмахер занят обслуживанием.

  • Парикмахер спит, если нет клиентов.

  • Первый клиент будит парикмахера.

Задача о железнодорожном перегоне

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

Ограничения:

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

  • Модификация переменных состояния должно выполняться в критической секции.

Примитивы синхронизации в Win32 API

Критическая секция

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

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

Доступ к критической секции защищается функцией EnterCriticalSection или TryEnterCriticalSection.Если критическая секция в настоящее время принадлежит другой нити, то вызов EnterCriticalSection приведет к блокировке нити до тех пор, пока нить, находящаяся в критической секции, выполнит функцию LeaveCriticalSection. Функция TryEnterCriticalSection проверяет занятость критической секции без блокировки нити и обычно вызывается в цикле.

Нить, захватившая критическую секцию, может повторно вызывать EnterCriticalSection, при этом блокировки не происходит. Чтобы освободить критическую секцию, нить должна вызвать LeaveCriticalSection столько раз, сколько вызывала EnterCriticalSection.

Любая нить процесса может использовать функцию DeleteCriticalSection, чтобы освободить системные ресурсы, которые были распределены при инициализации критической секции.

Соседние файлы в папке вар1