Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СП2_1 Синхронизация потоков.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
134.14 Кб
Скачать

Мьютексы

(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);

}