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

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

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

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

Необходимость в синхронизации потоков

В главе 7 были продемонстрированы методы создания рабочих потоков и управления ими в условиях, когда каждый рабочий поток обращался к собственным ресурсам. В приведенных в главе 7 примерах каждый поток обрабатывает отдельный файл или отдельную область памяти, но даже и в этом случае возникает необходимость в простейшей синхронизации во время создания и завершения потоков. Так, в программе grepMT все рабочие потоки выполняются независимо друг от друга, но главный поток должен ожидать завершения рабочих потоков, прежде чем вывести сгенерированные ими результаты. Заметьте, что главный поток разделяет общую память с рабочими потоками, но структура программы гарантирует, что главный поток не получит доступа к памяти до тех пор, пока рабочий поток не завершит своего выполнения.

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

Однако во многих случаях требуется, чтобы выполнение двух и более потоков могло координироваться на протяжении всего времени жизни каждой из них. Например, несколько потоков могут обращаться к одной и той же переменной или набору переменных, и тогда возникает вопрос о взаимоисключающем доступе. В других случаях поток не может продолжать выполнение до тех пор, пока другой поток не достигнет определенного этапа выполнения. Каким образом программист может получить уверенность в том, что, например, два или более потоков не попытаются одновременно изменить данные, хранящиеся в глобальной памяти, такие, например, как статистические данные о производительности? Как, далее, программист может добиться того, чтобы поток не предпринимал попыток удаления элемента из очереди, если очередь не содержит хотя (бы одного элемента?

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

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

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

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

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