Читаем Системное программирование в среде Windows полностью

• Планировщик переводит поток в состояние ожидания (wait state), если он выполняет функцию ожидания несигнализирующих объектов, например, потоков или процессов, или перехода в сигнальное состояние объектов синхронизации, о чем говорится в главе 8. Операции ввода/вывода также будут ожидать завершения передачи дисковых или иных данных, но ожидание может быть вызвано и другими многочисленными функциями. О потоках, находящихся в состоянии ожидания, нередко говорят как о блокированных (blocked) или спящих (sleeping).

• Поток находится в состоянии готовности (ready state), если она может выполняться. Планировщик в любой момент может перевести такой поток в состояние выполнения. Когда процессор станет доступным, планировщик запустит тот из потоков, находящихся в состоянии готовности, который обладает наивысшим приоритетом, а при наличии нескольких потоков с одинаковым высшим приоритетом запущен будет та, который пребывал в состоянии готовности дольше всех. При этом поток проходит через состояние простоя (standby state), или резервное состояние.

• Обычно, в соответствии с приведенным описанием, планировщик помещает поток, находящийся в состоянии готовности, на любой доступный процессор. Программист может указать маску родства процессоров (processor affinity mask) для потока (см. главу 9), предоставляя потоку процессоры, на которых он может выполняться. Используя этот способ, программист может распределять процессоры между потоками. Соответствующими функциями являются SetProcessorAffinityMask и GetProcessorAffinityMask. Функция SetThreadIdealProcessor позволяет указать предпочтительный процессор, подлежащий использованию планировщиком при первой же возможности.

• После истечения кванта времени, отведенного выполняющемуся потоку, планировщик без ожидания переводит его в состояние готовности. В результате выполнения функции Sleep(0) поток также будет переведен из состояния выполнения в состояние готовности.

• Планировщик переводит ожидающий поток в состояние готовности сразу же, как только соответствующие дескрипторы оказываются в сигнальном состоянии, хотя при этом поток фактически проходит через промежуточное переходное состояние (transition state). В подобных случаях принято говорить о том, что поток пробуждается (wakes).

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

• Поток, независимо от его состояния, может быть приостановлен (suspended), и приостановленный поток не будет запущен, даже если он находится в состоянии готовности. В случае приостановки выполняющегося потока, независимо от того, по собственной ли инициативе или по инициативе потока, выполняющегося на другом процессоре, он переводится в состояние готовности.

• Поток переходит в состояние завершения (terminated state) тогда, когда его выполнение завершается, и остается в этом состоянии до тех пор, пока остается открытым хотя бы один из ее дескрипторов. Это позволяет другим потокам запрашивать состояние данного потока и его код завершения.

<p>Возможные ловушки и распространенные ошибки</p></span><span>

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

Существенно то, что потоки выполняются в асинхронном режиме. По отношению к ним не действует никакая система упорядочения, если только вы не создали ее явно. Именно асинхронное поведение потоков делает их столь полезными, однако при отсутствии должного внимания можно столкнуться с серьезными трудностями.

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

• Не делайте никаких предположений относительно очередности выполнения родительских и дочерних потоков. Вполне возможно, что дочерний поток будет выполняться вплоть до своего завершения, прежде чем родительский поток вернется из функции CreateThread, или наоборот, дочерний поток может вообще не выполняться в течение длительного периода времени. В случае же SMP-систем возможно параллельное выполнение родительского и одного или нескольких дочерних потоков.

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных