- •Отчет по лабораторной работе №2 По дисциплине «Операционные системы»
- •Порядок выполнения работы
- •Контрольные вопросы
- •Определение потока. Для чего используются потоки?
- •Для чего используется функция потока?
- •Какие параметры можно передавать в функцию потока?
- •Как запускаются потоки? Как запустить поток в приостановленном
- •Как остановить поток?
- •Как возобновить выполнение потока?
- •Как поток может отказаться от своего кванта времени?
- •В чем состоит проблема синхронизации потоков?
- •Что такое критические секции и для чего они используются?
- •Какие правила необходимо соблюдать при использовании критических секций?
Как остановить поток?
В объекте ядра «поток» имеется переменная — счетчик числа простоев данного по тока. При вызове CreateProcess или CreateThread он инициализируется значением, равным единице, которое запрещает системе выделять новому потоку процессорное время. Такая схема весьма разумна: сразу после создания поток не готов к выполнению, ему нужно время для инициализации.
После того как поток полностью инициализирован, CreateProcess или CreateThread проверяет, не передан ли ей флаг CREATE_SUSPENDED, и, если да, возвращает управление, оставив поток в приостановленном состоянии. В ином случае счетчик простоев обнуляется, и поток включается в число планируемых — если только он не ждет какого-то события (например, ввода с клавиатуры).
Создав поток в приостановленном состоянии, можно настроить некоторые его свойства (например, приоритет). Закончив настройку, необходимо разрешить выполнение потока. Для этого вызовите ResumeThread и передайте описатель потока, возвращенный функцией CreateThread (описатель можно взять и из структуры, на которую указывает параметр ppiProcInfo, передаваемый в CreateProcess).
DWORD ResumeThread(HANDLE hThread);
Если вызов ResumeThread прошел успешно, она возвращает предыдущее значение счетчика простоев данного потока; в ином случае — 0xFFFFFFFF.
Как возобновить выполнение потока?
Как поток может отказаться от своего кванта времени?
Поток может сообщить системе не выделять ему процессорное время на определенный период, вызвав:
VOID Sleep(DWORD dwMilliseconds);
Эта функция приостанавливает поток па dwMilliseconds миллисекунд. Отметим несколько важных моментов, связанных с функцией Sleep.
Вызывая Sleep, поток добровольно отказывается от остатка выделенного ему кванта времени.
Система прекращает выделять потоку процессорное время на период, примерно равный заданному. Если остановить поток на 100 мс, приблизительно на столько он и «заснет», хотя не исключено, что его сон продлится на несколько секунд или даже минут больше. Windows не является системой реального времени. Поток может возобновиться в заданный момент, но это зависит от того, какая ситуация сложится в системе к тому времени.
Можно вызвать Sleеp и передать в dwMilliseconds значение INFINITE, вообще запретив планировать поток. Но это не очень практично — куда лучше корректно завершить поток, освободив его стек и объект ядра.
Можно вызвать Sleep и передать в dwMilliseconds нулевое значение. Тогда поток откажется от остатка своего кванта времени и заставит систему подключить к процессору другой поток. Однако система может снова запустить данный поток, если других планируемых потоков с тем же приоритетом нет.
В чем состоит проблема синхронизации потоков?
Windows лучше всего работает, когда все потоки могут заниматься своим делом, не взаимодействуя друг с другом. Однако такая ситуация очень редка. Обычно поток создается для выполнения определенной работы, о завершении которой, вероятно, захочет узнать другой поток.
Все потоки в системе должны иметь доступ к системным ресурсам — кучам, последовательным портам, файлам, окнам и т д. Если один из потоков запросит монопольный доступ к какому-либо ресурсу, другим потокам, которым тоже нужен этот ресурс, не удастся выполнить свои задачи. А с другой стороны, просто недопустимо, чтобы потоки бесконтрольно пользовались ресурсами. Иначе может получиться так, что один поток пишет в блок памяти, из которого другой что-то считывает.
Потоки должны взаимодействовать друг с другом в двух основных случаях:
совместно используя разделяемый ресурс (чтобы не разрушить его);
когда нужно уведомлять другие потоки о завершении каких-либо операций.