Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 127 стр.

UptoLike

К сожалению, средств для проверки текущего значения счетчика без
изменения состояния семафора нет: функция ReleaseSemaphore позволяет
узнать предыдущее значение, но при этом обязательно увеличит его зна-
чение хотя бы на 1 (попытка увеличить на 0 или на отрицательную вели-
чину рассматривается как ошибка), а ожидающая функция обязательно
уменьшит счетчик, если семафор был свободен. Поэтому для определения
значения счетчика надо использовать что-то вроде приведенного ниже
примера:
LONG lCounter;
lCounter = 0;
if ( WaitForSingleObject( hSem, 0 ) == WAIT_OBJECT_0 )
ReleaseSemaphore( hSem, 1, &lCounter );
/* теперь переменная lCounter содержит значение счетчика */
Семафоры предназначены для ограничения числа потоков, имею-
щих одновременный доступ к какому-либо ресурсу.
Мьютексы
Объекты исключительного владения могут быть использованы в од-
но время не более чем одним потоком. В этом отношении мьютексы по-
добны критическим секциям, с той оговоркой, что работа с ними выпол-
няется в режиме ядра (при использовании критических секций переход в
режим ядра необязателен) и что мьютексы могут быть использованы для
межпроцессного взаимодействия, тогда как критические секции реализо-
ваны для применения внутри процесса.
Для захвата мьютекса используется ожидающая функция WaitFor..., а
для освобождения – функция ReleaseMutex. При создании мьютекса функ-
цией CreateMutex можно указать, чтобы он создавался сразу в занятом со-
стоянии:
#include <process.h>
#include <windows.h>
#define DEFAULT_SECURITY (LPSECURITY_ATTRIBUTES)NULL
unsigned __stdcall TProc( void *pdata )
{
WaitForSingleObject( hObject, 2000 );
WaitForSingleObject( hObject, 2000 );
Sleep( 1000 );
ReleaseMutex( (HANDLE)pdata );
ReleaseMutex( (HANDLE)pdata );
return 0;
}
Разработка параллельных приложений для ОС Windows
241
Семафоры
Семафор представляет собой счетчик, который считается свобод-
ным, если значение счетчика больше нуля, и занятым при нулевом значе-
нии. При создании семафора задаются его максимально допустимое и на-
чальное состояния. Ожидающие функции WaitFor... уменьшают значение
свободного семафора на 1, если счетчик ненулевой, или переходят в ре-
жим ожидания до тех пор пока кто-либо не увеличит значение семафора.
Увеличение счетчика осуществляется функцией ReleaseSemaphore:
#define DEFAULT_SECURITY (LPSECURITY_ATTRIBUTES)NULL
int main( void )
{
HANDLE hSem;
LONG lPrev;
hSem = CreateSemaphore( DEFAULT_SECURITY, 0, 5, NULL );
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_TIMEOUT */
ReleaseSemaphore( (HANDLE)dwData, 1, &lPrev );
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_OBJECT_0 */
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_TIMEOUT */
ReleaseSemaphore( (HANDLE)dwData, 2, &lPrev );
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_OBJECT_0 */
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_OBJECT_0 */
WaitForSingleObject( hSem, 100 );
/* код завершения WAIT_TIMEOUT */
CloseHandle( hSem );
return 0;
}
В примере создается семафор в первоначально занятом состоянии,
поэтому первое ожидание завершается по таймауту. После этого его счет-
чик увеличивается на 1, и следующее ожидание завершается успехом, при
этом счетчик семафора уменьшается и он снова становится занятым. В ре-
зультате третье ожидание завершается по таймауту. После этого счетчик
увеличивается на 2, и два последующих ожидания завершаются успехом,
после чего счетчик оказывается снова нулевым и третье ожидание завер-
шается по таймауту.
240
CIL и системное программирование в Microsoft .NET
240                          CIL и системное программирование в Microsoft .NET   Разработка параллельных приложений для ОС Windows                   241


     Семафоры                                                                         К сожалению, средств для проверки текущего значения счетчика без
     Семафор представляет собой счетчик, который считается свобод-               изменения состояния семафора нет: функция ReleaseSemaphore позволяет
ным, если значение счетчика больше нуля, и занятым при нулевом значе-            узнать предыдущее значение, но при этом обязательно увеличит его зна-
нии. При создании семафора задаются его максимально допустимое и на-             чение хотя бы на 1 (попытка увеличить на 0 или на отрицательную вели-
чальное состояния. Ожидающие функции WaitFor... уменьшают значение               чину рассматривается как ошибка), а ожидающая функция обязательно
свободного семафора на 1, если счетчик ненулевой, или переходят в ре-            уменьшит счетчик, если семафор был свободен. Поэтому для определения
жим ожидания до тех пор пока кто-либо не увеличит значение семафора.             значения счетчика надо использовать что-то вроде приведенного ниже
Увеличение счетчика осуществляется функцией ReleaseSemaphore:                    примера:

      #define DEFAULT_SECURITY (LPSECURITY_ATTRIBUTES)NULL                            LONG lCounter;
                                                                                      lCounter = 0;
     int main( void )                                                                 if ( WaitForSingleObject( hSem, 0 ) == WAIT_OBJECT_0 )
     {                                                                                  ReleaseSemaphore( hSem, 1, &lCounter );
       HANDLE hSem;                                                                   /* теперь переменная lCounter содержит значение счетчика */
       LONG      lPrev;                                                               Семафоры предназначены для ограничения числа потоков, имею-
       hSem = CreateSemaphore( DEFAULT_SECURITY, 0, 5, NULL );                   щих одновременный доступ к какому-либо ресурсу.
       WaitForSingleObject( hSem, 100 );                                              Мьютексы
          /* код завершения WAIT_TIMEOUT */                                           Объекты исключительного владения могут быть использованы в од-
       ReleaseSemaphore( (HANDLE)dwData, 1, &lPrev );                            но время не более чем одним потоком. В этом отношении мьютексы по-
       WaitForSingleObject( hSem, 100 );                                         добны критическим секциям, с той оговоркой, что работа с ними выпол-
          /* код завершения WAIT_OBJECT_0 */                                     няется в режиме ядра (при использовании критических секций переход в
       WaitForSingleObject( hSem, 100 );                                         режим ядра необязателен) и что мьютексы могут быть использованы для
          /* код завершения WAIT_TIMEOUT */                                      межпроцессного взаимодействия, тогда как критические секции реализо-
       ReleaseSemaphore( (HANDLE)dwData, 2, &lPrev );                            ваны для применения внутри процесса.
       WaitForSingleObject( hSem, 100 );                                              Для захвата мьютекса используется ожидающая функция WaitFor..., а
          /* код завершения WAIT_OBJECT_0 */                                     для освобождения – функция ReleaseMutex. При создании мьютекса функ-
       WaitForSingleObject( hSem, 100 );                                         цией CreateMutex можно указать, чтобы он создавался сразу в занятом со-
          /* код завершения WAIT_OBJECT_0 */                                     стоянии:
       WaitForSingleObject( hSem, 100 );
          /* код завершения WAIT_TIMEOUT */                                           #include 
       CloseHandle( hSem );                                                           #include 
       return 0;                                                                      #define DEFAULT_SECURITY   (LPSECURITY_ATTRIBUTES)NULL
     }
     В примере создается семафор в первоначально занятом состоянии,                   unsigned __stdcall TProc( void *pdata )
поэтому первое ожидание завершается по таймауту. После этого его счет-                {
чик увеличивается на 1, и следующее ожидание завершается успехом, при                   WaitForSingleObject( hObject, 2000 );
этом счетчик семафора уменьшается и он снова становится занятым. В ре-                  WaitForSingleObject( hObject, 2000 );
зультате третье ожидание завершается по таймауту. После этого счетчик                   Sleep( 1000 );
увеличивается на 2, и два последующих ожидания завершаются успехом,                     ReleaseMutex( (HANDLE)pdata );
после чего счетчик оказывается снова нулевым и третье ожидание завер-                   ReleaseMutex( (HANDLE)pdata );
шается по таймауту.                                                                     return 0;
                                                                                      }