Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

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




Имеется четыре функции для работы с критическими разделами.

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

CRITICAL_SECTION cs; // объявление глобальной переменной
  • Тип данных CRITICAL_SECTION является структурой, но ее поля используются только самой Windows.

Объект критический раздел сначала должен быть инициализирован одним из потоков программы с помощью функции:

InitializeCriticalSection(&cs);
  • Эта функция создает критический раздел с именем cs. Чаще всего этот объект создается при инициализации процесса, т.е. главным потоком в функции WinMain.

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

EnterCriticalSection(&cs);
  • В этот момент именно этот поток становится владельцем объекта.

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

LeaveCriticalSection(&cs);
  • В этот момент второй поток, задержанный в функции EnterCriticalSection, станет владельцем критического раздела, и его выполнение будет возобновлено.

Обычно вызовы функций EnterCriticalSection и LeaveCriticalSection осуществляют до и после фрагмента кода потока, при выполнении которого могут возникнуть проблемы с разделением данных:

EnterCriticalSection(&cs); // критичекий фрагмент кода потока................................... LeaveCriticalSection(&cs);

Когда объект критический раздел больше не нужен процессу, его можно удалить (обычно в функции WinMain) с помощью функции:

DeleteCriticalSection(&cs);

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

Механизм критических разделов основан на принципе взаимного исключения (mutual exclusion). Только один поток может быть владельцем критического раздела в каждый конкретный момент времени. Следовательно, один поток может войти в критический раздел, установить значения полей структуры и выйти из критического раздела. Другой поток, использующий эту структуру, также мог бы войти в критический раздел с тем же именем перед осуществлением доступа к полям структуры, а затем выйти из критического раздела.

Следует отметить, что

  • Объект критический раздел не может быть программой перемещен или скопирован. Процесс также не должен модифицировать объект, а должен обращаться с ним, как с “черным ящиком”.
  • Возможно определение нескольких объектов типа CRITICAL_SECTION. Если в программе есть несколько потоков, то потоки, разделяющие один набор данных, могут использовать первый объект типа CRITICAL_SECTION, другие потоки, разделяющие другие наборы данные, - второй объект, и т.д.

· · Следует очень осторожно использовать использование критического раздела в главном потоке. Если вторичный поток проводит слишком много времени в его собственном критическом разделе, то это может привести к “зависанию” главного потока на слишком большой период времени.

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

Но

Бывают случаи, когда необходимо синхронизировать действия потоков различных процессов, которые разделяют какие-либо ресурсы (например, память). Использовать критические разделы в такой ситуации нельзя. Вместо них используются мьютексы (mutex object).

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

Уведомление при помощи посылки сообщений

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

Рассмотрим случай, когда какому-либо потоку необходимо проинформировать первичный поток (или другой поток, умеющий обрабатывать сообщения, т.е. имеющий оконную процедуру) о своем состоянии или о том, что этому потоку следует что-либо сделать.

Любой поток может функцией SendMessage (или PostMessage) послать в оконную процедуру потока, умеющего обрабатывать сообщения, сообщение, определенное в программе. Получив такое сообщение, оконная процедура потока-адресата может сделать какие-либо действия, или может просто быть информированной о состоянии потока-отправителя, пославшего это сообщение.

Например, модифицируем функцию вторичного потока предыдущего примера так, чтобы она посылала сообщение в первичный поток через каждые 1000 итераций работы своего цикла, а функцию главного окна приложения - чтобы она обрабатывала это сообщение:

... #define MESSAGE_FROM_OTHER_THREAD (WM_USER+1)... LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {... switch(msg) {... case MESSAGE_FROM_OTHER_THREAD: { // первичный поток может здесь обработать данное сообщение ... };break;... } return 0l; } void ThreadFun(void *lpvoid) { long num=0;... while(!p->stop) { num++; if (num%1000==0) { // посылка сообщения первичному потоку SendMessage(p->wnd,MESSAGE_FROM_OTHER_THREAD,0,0L); }... } _endthread(); } Объекты ядра

Следующие объекты ядра бывают в свободном или занятом состоянии:

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

Так, объекты ядра «процесс» сразу после создания всегда находятся в занятом состоянии. В момент завершения процесса операционная система автоматически освобождает его объект ядра "процесс", и он на всегда остается в этом состоянии

Объект ядра «процесс» пребывает в занятом состоянии, пока выполняется сопоставленный с ним процесс, и переходит в свободное состояние, когда процесс завершается Внутри этого объекта поддерживается булева переменная, которая при создании объекта инициализируется как FALSE («занято"). По окончании работы процесса операционная система меняет значение этой переменной на TRUE, сообщая тем самым, что объект свободен.

Существуют специальные функции, которые позволяют потоку ждать перехода определенного объекта ядра в свободное состояние.



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


Дата добавления: 2014-01-11; Просмотров: 469; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.