#include "stdafx.h" #include #include #include #include #include using namespace std; struct TMySemaphore { //Наш семафор HANDLE HEvent;//Событие int Count;//Сколько ещё можно внести потоков int Max;//Макс. кол-во int waiting;//Сколько ждет } Sem; HANDLE h[5]; //Дескрипторы потоков int d[5];//Идентификаторы потоков int q[10];//Общий ресурс(массив) int i; DWORD dwError; LPTSTR hlocal; void CreateMySemaphore(TMySemaphore S, int init,int max, string name) { S.Count = init;//Сколько еще может войти потоков(создаётся счётчик) S.Max = max;//Макс. число потоков, которое может войти if (init > max) { cout << "Start value must be less then maximal\n" << GetLastError(); _getch(); } S.HEvent = CreateEvent(NULL, false, true, (LPCWSTR)&name);//Создаём событие S.waiting = 0; //Сколько ждет } void WaitForMySemaphore(TMySemaphore S) {//Ждём семафора if (S.Count > 0) {//Если еще может кто-то войти S.Count--;//Уменьшаем } else { S.waiting++;//Увел. число ждущих WaitForSingleObject(S.HEvent, INFINITE);//Ждём, когда кто-нибудь просигналит событие(освободит семафор) } } void ReleaseMySemaphore(TMySemaphore S) {//Освоб. семафор if (S.Count == 0) {//Если заполнено SetEvent(S.HEvent);//Сигналим событие } if (S.waiting > 0) {//Если кто-то ждет S.waiting--;//Уменьшаем число ждущих } else { S.Count++;//Увел. число возможных потоков } if (S.Count > S.Max) { cout << "Too many!!!\n"; } } void CloseMySemaphore(TMySemaphore S) {//Закрываем семафор CloseHandle(S.HEvent);//Закрываем дескриптор события } DWORD proc1(DWORD dd) {//Процедура добавляющих потоков int x, i, j, ip; DWORD id; id = GetCurrentThreadId();//получаем идентификатор потока ip = 0;//Пока еще не нашли for (i = 1; i <= 5; i++) {//Ищем номер потока if (d[i] == id) ip = i; } for (i = 1; i <= 5; i++) {//Меняем пять чисел //Пишем состояние семафора cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; cout << ip << " is waiting\n"; WaitForMySemaphore(Sem);//Ждем семафора Sleep(1000);//задержка(1 сек.) cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; j = (rand() % 10) + 1;//[1..10] x = rand() % 100; //Пишем, какое число мы заменили cout << ip << " Thread#" << ip << " has put a number into place:" << j << "-" << x << "\n"; q[j] = x;//Меняем в массиве сл. число на сл. месте cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; Sleep(1000); ReleaseMySemaphore(Sem);//Освоб семафор cout << ip << " Releasing\n"; cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; } return 0; } DWORD proc2(DWORD dd) {//процедура вынимающего потока int i, j, x, ip; DWORD id; id = GetCurrentThreadId();//получаем идентификатор потока ip = 0; for (i = 1; i <= 5; i++) {//Ищем номер потока if (d[i] == id) ip = i; } for (i = 1; i <= 15; i++) {//смотрим случайный элемент массива //Состояние семафора cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; cout << ip << " Waiting\n"; WaitForMySemaphore(Sem);//Ждём семафора Sleep(1000); cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; j = (rand() % 10) + 1; //Место x = q[j];//Вынимаем число из массива //Какое число мы посмотрели cout << ip << " Thread#" << ip << " has got a number from place:" << j << "-" << x << "\n"; cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; Sleep(1000); ReleaseMySemaphore(Sem);//Освоб. семафор cout << ip << " Releasing\n"; cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n"; } return 0; } void main() {//Основная программа setlocale(LC_ALL, "russian_russia"); srand(time(NULL)); //AllocConsole;//Создаем консоль cout << "Was:"; for (i = 1; i <= 10; i++) {//Заполняем и выводим массив q[i] = rand() % 100; cout << q[i] << " "; } cout << "\n"; CreateMySemaphore(Sem, 3, 3, "EventSemaphore");//Созд. семафор for (i = 1; i <= 3; i++) { h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc1, NULL, 0, (LPDWORD)d[i]);//Создаём 3 кладущих потока if (h[i] == 0) cout << (GetLastError()); } for (i = 4; i <= 5; i++) { h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc2, NULL, 0, (LPDWORD)d[i]);//Создаём 2 вынимающих потока dwError = GetLastError(); if (h[i] == 0) cout << (dwError); // FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER, nil, dwError; MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); hlocal; 0; nil ) } WaitForMultipleObjects(5, h,true, INFINITE);//Ждём завершения всех потоков for (i = 1; i <= 5; i++) { CloseHandle(h[i]);//Закрываем дескрипторы потоков } CloseMySemaphore(Sem);//Закрываем семафор cout << "Is:"; //то, что получилось for (i = 1; i <= 10; i++) { //Выводим массив cout << q[i] << " "; } _getch(); //FreeConsole;//Закрываем консоль }