Шаг 117 - CreateSemaphore, ReleaseSemaphore

Очень полезно сначало прочитать MSDN: "Шаг 81 - Что такое семафоры (Semaphore)". Создается семафор функцией CreateSemaphore():

HANDLE CreateSemaphore
(
	LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,	// атрибут доступа
	LONG lInitialCount,			// инициализированное начальное состояние счетчика
	LONG lMaximumCount,			// максимальное количество обращений
	LPCTSTR lpName				// имя объекта
);

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

BOOL ReleaseSemaphore
(
	HANDLE hSemaphore,		// хенд семафора
	LONG lReleaseCount, 	// на сколько изменять счетчик
	LPLONG lpPreviousCount	// предыдущее значение
);

При успешном выполнении возвращаемое значение ненулевое. Для уничтожения семафора нужно вызвать CloseHandle(). Давайте рассмотрим пример. Вот он:

// TestSemaphore.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "process.h" 

HANDLE hSemaphore;
LONG cMax = 2;

void Test1(void *);
void Test2(void *);
void Test3(void *);

void main()
{
	hSemaphore = CreateSemaphore( 
	    NULL,	// нет атрибута
	    cMax,	// начальное состояние
	    cMax,	// максимальное состояние
	    NULL	// без имени
	);

	if (!hSemaphore == NULL) 
	{
		if (_beginthread(Test1,1024,NULL)==-1)
			cout << "Error begin thread " << endl;
		if (_beginthread(Test2,1024,NULL)==-1)
			cout << "Error begin thread " << endl;
		if (_beginthread(Test3,1024,NULL)==-1)
		cout << "Error begin thread " << endl;
		Sleep(10000);
		CloseHandle(hSemaphore);
	}
	else
		cout << "error create semaphore" << endl;
}

void Test1(void *)
{
	cout << "Test1 Running" << endl;
	DWORD dwWaitResult; 
	while(dwWaitResult!=WAIT_OBJECT_0)
	{
		dwWaitResult = WaitForSingleObject( 
			hSemaphore,	// указатель на семафор
			1		// интерфал ожидания
		);
		cout << "Test 1 TIMEOUT" << endl;
	}
	Sleep(1000);
	if (ReleaseSemaphore(       
			hSemaphore,	// указатель на светофор
			1,		// изменяет счетчик на 1
	        NULL)
	)
	cout << " ReleaseSemaphore Ok Test1" << endl;   
	_endthread();
}

void Test2(void *)
{
	cout << "Test2 Running" << endl;
	DWORD dwWaitResult;
	while(dwWaitResult!=WAIT_OBJECT_0)
	{
		dwWaitResult = WaitForSingleObject(hSemaphore,1);
		cout << "Test 2 TIMEOUT" << endl;
	}
	Sleep(1000);
	if (ReleaseSemaphore(hSemaphore,1,NULL))
		cout << " ReleaseSemaphore Ok Test2" << endl;  
	_endthread();
}

void Test3(void *)
{
	cout << "Test2 Running" << endl;
	DWORD dwWaitResult; 
	while(dwWaitResult!=WAIT_OBJECT_0)
	{
		dwWaitResult = WaitForSingleObject(hSemaphore,1);
		cout << "Test 3 TIMEOUT" << endl;
	}
	if (ReleaseSemaphore(hSemaphore,1,NULL))
		cout << " ReleaseSemaphore Ok Test3" << endl;  
	_endthread();
}

В данном примере создается семафор. Запускаются три потока, каждый из которых обрашается к семафору. Вот только разрешается обращаться всего двум потокам. Поэтому Test3 будет ждать, пока кто-то освободит семафор. Вот результат:

.......
Test 3 TIMEOUT
Test 3 TIMEOUT
Test 3 TIMEOUT
Test 3 TIMEOUT
 ReleaseSemaphore Ok Test1
Test 3 TIMEOUT
 ReleaseSemaphore Ok Test2
 ReleaseSemaphore Ok Test3
Press any key to continue

Как видите третий поток ждет. И как только освободился семафор он может дальше что-то делать.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 1.05.2001