- •1. Потоки. Определение. Области применения
- •2. Необходимость создания потоков
- •3. Функция потока. Создание потока
- •4. Завершение потока
- •5. Возврат управления функцией потока
- •6. Приостановка и возобновление потоков
- •7. Функция Sleep
- •8. Переключение потоков
- •9. Синхронизация потоков
- •9.1. Критические секции
- •Void InitializeCriticalSection(pcritical_section pcs);
- •Void DeleteCriticalSection(pcritical_section pcs);
- •Void EnterCriticalSection(pcritical_section pcs);
- •Void LeaveCriticalSection(pcritical_section pcs);
- •9.2. Правила использования критических секций
- •10. Порядок выполнения работы
- •11. Контрольные вопросы
Void InitializeCriticalSection(pcritical_section pcs);
Эта функция инициализирует элементы структуры CRITICAL_SECTION, на которую указывает параметр pcs. Поскольку вся работа данной функции заключается в инициализации нескольких переменных-членов, она не дает сбоев и поэтому ничего не возвращает (void). InitializeCriticalSection должна быть вызвана до того, как один из потоков обратится к EnterCriticalSection.
Если известно, что структура CRITICAL_SECTION больше не понадобится ни одному потоку, можно удалить ее, вызвав DeleteCriticalSection:
Void DeleteCriticalSection(pcritical_section pcs);
Она сбрасывает все переменные-члены внутри этой структуры. Естественно, нельзя удалять критическую секцию в тот момент, когда ею все еще пользуется какой-либо поток.
Участок кода, работающий с разделяемым ресурсом, предваряется вызовом:
Void EnterCriticalSection(pcritical_section pcs);
Первое, что делает EnterCriticalSection, — исследует значения элементов структуры CRITICAL_SECTION. Если ресурс занят, в них содержатся сведения о том, какой поток пользуется ресурсом. EnterCriticalSection выполняет следующие действия.
Если ресурс свободен, EnterCriticalSection модифицирует элементы структуры, указывая, что вызывающий поток занимает ресурс, после чего немедленно возвращает управление, и поток продолжает свою работу (получив доступ к ресурсу).
Если значения элементов структуры свидетельствуют, что ресурс уже захвачен вызывающим потоком, EnterCriticalSection обновляет их, отмечая тем самым, сколько раз подряд этот поток захватил ресурс, и немедленно возвращает управление. Такая ситуация бывает нечасто — лишь тогда, когда поток два раза подряд вызывает EnterCriticalSection без промежуточного вызова LeaveCritical Section.
Если значения элементов структуры указывают на то, что ресурс занят другим потоком, EnterCriticalSection переводит вызывающий поток в режим ожидания. Это потрясающее свойство критических секций: поток, пребывая в ожидании, не тратит ни кванта процессорного времени. Система запоминает, что данный поток хочет получить доступ к ресурсу, и - как только поток, занимавший этот ресурс, вызывает LeaveCriticalSection — вновь начинает выделять нашему потоку процессорное время. При этом она передает ему ресурс, автоматически обновляя элементы структуры CRITICAL_SECTION.
Даже если два потока на многопроцессорной машине одновременно вызовут EnterCriticalSection, функция все равно корректно справится со своей задачей: один поток получит ресурс, другой — перейдет в ожидание.
Вместо EnterCriticalSection можно воспользоваться (в Windows 98 не реализована);
BOOL TryEnterCriticalSection(PCRITICAL_SECTION pcs);
Эта функция никогда не приостанавливает выполнение вызывающего потока. Но возвращаемое ею значение сообщает, получил ли этот поток доступ к ресурсу. Если при ее вызове указанный ресурс занят другим потоком, она возвращает FALSE.
В конце участка кода, использующего разделяемый ресурс, должен присутствовать вызов.