- •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. Контрольные вопросы
7. Функция Sleep
Поток может сообщить системе не выделять ему процессорное время на определенный период, вызвав:
VOID Sleep(DWORD dwMilliseconds);
Эта функция приостанавливает поток па dwMilliseconds миллисекунд. Отметим несколько важных моментов, связанных с функцией Sleep.
-
Вызывая Sleep, поток добровольно отказывается от остатка выделенного ему кванта времени.
-
Система прекращает выделять потоку процессорное время на период, примерно равный заданному. Если остановить поток на 100 мс, приблизительно на столько он и «заснет», хотя не исключено, что его сон продлится на несколько секунд или даже минут больше. Windows не является системой реального времени. Поток может возобновиться в заданный момент, но это зависит от того, какая ситуация сложится в системе к тому времени.
-
Можно вызвать Sleеp и передать в dwMilliseconds значение INFINITE, вообще запретив планировать поток. Но это не очень практично — куда лучше корректно завершить поток, освободив его стек и объект ядра.
-
Можно вызвать Sleep и передать в dwMilliseconds нулевое значение. Тогда поток откажется от остатка своего кванта времени и заставит систему подключить к процессору другой поток. Однако система может снова запустить данный поток, если других планируемых потоков с тем же приоритетом нет.
8. Переключение потоков
Функция SwitchToThread позволяет подключить к процессору другой поток (если он есть):
BOOL SwitchToThread();
При вызове этой функции, система проверяет, есть ли поток, которому не хватает процессорного времени. Если нет, SwitchToThread немедленно возвращает управление, а если да, планировщик отдает ему дополнительный квант времени (приоритет этого потока может быть ниже, чем у вызывающего). По истечении этого кванта планировщик возвращается в обычный режим работы.
SwitchToThread позволяет потоку, которому не хватает процессорного времени, отнять этот ресурс у потока с более низким приоритетом. Она возвращает FALSE, если на момент ее вызова в системе нет ни одного потока, готового к исполнению, в ином случае — ненулевое значение.
Вызов SwitchToThread аналогичен вызову Sleep с передачей в dwMilliseconds нулевого значения. Разница лишь в том, что SwitchToThread дает возможность выполнять потоки с более низким приоритетом, которым не хватает процессорного времени, а Sleep действует без оглядки на «голодающие» потоки. В Windows 98 функция SwitchToThread лишь определена, но не реализована.
9. Синхронизация потоков
Windows лучше всего работает, когда все потоки могут заниматься своим делом, не взаимодействуя друг с другом. Однако такая ситуация очень редка. Обычно поток создается для выполнения определенной работы, о завершении которой, вероятно, захочет узнать другой поток.
Все потоки в системе должны иметь доступ к системным ресурсам — кучам, последовательным портам, файлам, окнам и т д. Если один из потоков запросит монопольный доступ к какому-либо ресурсу, другим потокам, которым тоже нужен этот ресурс, не удастся выполнить свои задачи. А с другой стороны, просто недопустимо, чтобы потоки бесконтрольно пользовались ресурсами. Иначе может получиться так, что один поток пишет в блок памяти, из которого другой что-то считывает.
Потоки должны взаимодействовать друг с другом в двух основных случаях:
-
совместно используя разделяемый ресурс (чтобы не разрушить его);
-
когда нужно уведомлять другие потоки о завершении каких-либо операций.