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

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

<p>Другие функции взаимоблокировки</p>

Ранее уже было продемонстрировано, что функции InterlockedIncrement и InterlockedDecrement могут пригодиться в тех случаях, когда все, что требуется — это выполнение простейших операций над переменными, доступ к которым разделяется несколькими потоками. Используя некоторые другие функции, вы можете выполнять атомарные операции, позволяющие осуществлять сравнение и обмен значениями пар переменных.

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

Функция InterlockedExchange сохраняет значение одной переменной в другой. 

LONG InterlockedExchange(LPLONG Target, LONG Value) 

Эта функция возвращает текущее значение переменной, на которую указывает параметр Target, и устанавливает значение этой переменной равным Value. Функция InterlockedExchangeAdd прибавляет второе значение к первому. 

LONG InterlockedExchangeAdd(PLONG Addend, LONG Increment) 

Значение Increment прибавляется к значению переменной, на которую указывает параметр Addend, а начальное значение этой переменной возвращается функцией. Данная функция позволяет увеличивать значение переменной на 2 (и более) атомарным образом, чего невозможно добиться последовательными вызовами функции InterlockedIncrement.

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

PVOID InterlockedCompareExchange(PVOID *Destination, PVOID Exchange, PVOID Comparand) 

Эта функция выполняет атомарным образом следующие действия (использование типа данных PVOID для двух последних параметров может казаться вам непонятным):

Temp = *Destination;

if (*Destination == Comparand) *Destination = Exchange;

return Temp;

Одним из вариантов применения этой функции является управление блокировкой с целью реализации критического участка кода. *Destination является переменной блокировки (lock variable), причем значению 1 соответствует разблокированное состояние, а значению 0 — блокированное. Значение Exchange задается равным 0, a Comparand — 1. Вызывающему потоку известно, что она владеет критическим участком, если функция возвращает 1. В противном случае вызывающий поток должен "уснуть", или выполнить ожидание в состоянии занятости ("spin"), то есть совершать в течение короткого промежутка времени цикл, в котором ничего не делается, с той только целью, чтобы выждать некоторое время, а затем вновь повторить попытку. По существу, именно такой цикл и выполняет функция EnterCriticalSection, ожидая перехода в сигнальное состояние объекта CRITICAL_SECTION с ненулевым значением спин-счетчика; для получения более подробной информации по этому вопросу обратитесь к главе 9.

<p>Учет факторов производительности при организации управленияпамятью</p>

Программа 9.1, приведенная в следующей главе, позволяет исследовать различные аспекты производительности в условиях, когда несколько потоков соревнуются между собой за право обладания разделяемыми ресурсами. Аналогичные эффекты будут наблюдаться и в случае, когда потоки привлекаются для управления памятью с использованием функций malloc и free из многопоточной стандартной библиотеки С, поскольку эти функции используют объекты CRITICAL_SECTION для синхронизации доступа к структуре данных кучи (вы можете в этом сами убедиться, просмотрев исходный код библиотеки С). Ниже описаны два возможных способа улучшения производительности.

• Каждый поток, управляющий памятью, может создать дескриптор типа HANDLE для собственной кучи с помощью функции HeapCreate (глава 5). После этого для распределения памяти вместо функций malloc и free можно использовать функции HeapAlloc и HeapFree.

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

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

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

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