
Мьютексы
(mutual exclusion - mutex)
Функции для работы с мьютексами:
1.
HANDLE CreateMutex (LPSECURITY_ATTRIBUTES
lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);
2.
BOOL ReleaseMutex( HANDLE hMutex);
3.
BOOL CloseHandle( HANDLE hMutex);
Пример использования мьютекса для синхронизации работы двух потоков при заполнении массива значениями и его обработке.
// Объявление глобальных данных
FLOAT y[20], s;
HANDLE hMutex;
// Функция потока 1
DWORD WINAPI ThreadFunc1(PVOID pvParam)
{ int i; DWORD dwResult = 0, n=1;
struct PARAM *p= (struct PARAM *) pvParam;
while (!p->stop) {
WaitForSingleObject( hMutex, INFINITE );
for ( i = 0; i < 20; i++ ) y[i]=2.5*(n+i)*sin(3.9*i+n);
n++;
ReleaseMutex( hMutex );
}
return(dwResult);
}
// Функция потока 2
DWORD WINAPI ThreadFunc2(PVOID pvParam)
{ int i; DWORD dwResult = 0;
struct PARAM *p= (struct PARAM *) pvParam;
while (!p->stop) {
WaitForSingleObject( hMutex, INFINITE );
for ( i = 0, s=0; i < 20; i++ ) s+=y[i];
s/=20;
ReleaseMutex( hMutex );
}
return(dwResult);
}
// --- Функция WinMain
int APIENTRY WinMain(…)
{
// Создание объекта мьютекс
hMutex = CreateMutex( NULL, FALSE, NULL );
…
// Удаление объекта мьютекс (при необходимости)
CloseHandle( hMutex );
…
}
Потоки по очереди заполняют массив значениями и производят его обработку.
Семафоры
1.
HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES
lpSemaphAttrib, LONG lInitialCount,
LONG lMaximumCount, LPCTSTR lpName);
2.
BOOL ReleaseSemaphore( HANDLE hSem,
LONG lReleaseCount, LPLONG lpPreviousCount);
3.
BOOL CloseHandle( HANDLE hSem );
Пример использования семафоров.
Программа производит обработку клиентских запросов, которые вначале помещают в очередь длиной 20. Обработку запросов выполняют три потока. Для учета количества запросов в очереди используется семафор, для безопасного помещения запросов в очередь и извлечения из нее используются критические секции.
// Описание глобальных данных
HANDLE hSem;
CRITICAL_SECTION cs;
struct Query { // описание структуры запроса
LONG lClientId;
char cQueryText[256]; };
struct Query Queue[20]; // создание очереди
LONG lPreviousCount=0;
// Функция потока 1
DWORD WINAPI ThreadFunc1(PVOID pvParam)
{ int i; DWORD dwResult=0;
struct Query Query1; // обрабатываемый запрос
struct PARAM *p= (struct PARAM *) pvParam;
while (!p->stop) {
// ожидание наличия в очереди запросов
WaitForSingleObject(hSem, INFINITE);
// извлечение 1-го запроса из очереди
EnterCriticalSection(&cs);
Query1 = Queue[0];
for (i=0; i< lPreviousCount; i++)
Queue [i]= Queue [i+1];
LeaveCriticalSection(&cs);
// обработка запроса Query1 в потоке
…
}
return(dwResult);
}
// Функция потока 2
DWORD WINAPI ThreadFunc2(PVOID pvParam)
{ // содержимое функции потока 2
// аналогично потоку 1
…
}
// Функция потока 3
DWORD WINAPI ThreadFunc3(PVOID pvParam)
{ // содержимое функции потока 3
// аналогично потоку 1
…
}
// --- Функция WinMain
int APIENTRY WinMain(…)
{
struct Query InQuery; // буфер для нового запроса
// Создание объекта семафор
hSem = CreateSemaphore( NULL, 0, 20, NULL );
// Создание объекта критический раздел
InitializeCriticalSection(&cs);
…
// получение запроса от клиента и помещение
// его в очередь
InQuery = GetQuery();
// увеличение числа запросов и счетчика на 1
if (ReleaseSemaphore(hSem, 1, &lPreviousCount))
{
EnterCriticalSection(&cs);
Queue[lPreviousCount] = InQuery;
LeaveCriticalSection(&cs);
}
else // очередь заполнена, запросу отказано
RejectQuery(InQuery);
…
// Удаление объектов семафор и
// критической раздел (при необходимости)
CloseHandle(hSem);
DeleteCriticalSection(&cs);
…
}