Студопедия

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

КАТЕГОРИИ:

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






Crytical Sections






В составе API ОС Windows имеются специальные и эффективные функции для организации входа в критическую секцию и выхода из нее потоков одного процесса в режиме пользователя. Они называются EnterCriticalSection и LeaveCriticalSection и имеют в качестве параметра предварительно проинициализированную структуру типа CRITICAL_SECTION.

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

CRITICAL_SECTION cs;

DWORD WINAPI SecondThread()

{

InitializeCriticalSection(& cs);

EnterCriticalSection(& cs);

… критический участок кода

LeaveCriticalSection(& cs);

}

main ()

{

InitializeCriticalSection(& cs);

CreateThread(NULL, 0, SecondThread, …);

EnterCriticalSection(& cs);

… критический участок кода

LeaveCriticalSecLion(& cs);

DeleteCriticalSection(& cs);

}

Функции EnterCriticalSection и LeaveCriticalSection реализованы на основе Interlocked-функций, выполняются атомарным образом и работают очень быстро. Существенным является то, что в случае невозможности входа в критический участок поток переходит в состояние ожидания. Впоследствии, когда такая возможность появится, поток будет " разбужен" и сможет сделать попытку входа в критическую секцию. Механизм пробуждения потока реализован с помощью объекта ядра " событие" (event), которое создается только в случае возникновения конфликтной ситуации.

Пример организации синхронизации:

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

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

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

Для условной синхронизации воспользуемся двумя семафорами. Зна­чение первого семафора показывает, сколько ячеек в буфере свободно. Ячей­ка свободна, когда в нее еще не осуществлялась запись или ячейка быта про­читана. Значение второго семафора показывает, сколько ячеек в буфере заня­то. Естественно, операция записи не может быть выполнена, пока количество занятых ячеек равно 100 (или количество свободных ячеек равно 0), и операция чтения не может быть выполнена, пока количество свободных ячеек рав­но 100 (или количество занятых ячеек равно 0). Для блокировки потока вос­пользуемся: условиями, заключенными в скобки, исходя из особенностей по­ведения семафоров.

 

#include < stdio.h>

#include< stdlib.h>

#include < conio.h>

#include< windows.h>

const int n=100, //длина буфера

m=7, //количество производителей

k=3; //количество потребителей

int buf[n], front=0, rear=0;

HANDLE hSemFull, hSemEmpty, //семафоры для условной синхронизации

hMutexD, hMutexF; //мьютексы для исключительного доступа


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

mylektsii.su - Мои Лекции - 2015-2024 год. (0.007 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал