#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]; //Дескрипторы потоков LPDWORD d[5];//Идентификаторы потоков int q[10];//Общий ресурс(массив) int i; DWORD dwError; LPTSTR hlocal; HANDLE ex; int ipex,k; void CreateMySemaphore(TMySemaphore *S, int init, int max, string name) { S->Count = init;//Сколько еще может войти потоков(создаётся счётчик) S->Max = max;//Макс. число потоков, которое может войти if (init > max) { cout << "Начальное значение должно быть меньше максимального\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++;//Увел. число ждущих ex = (HANDLE)GetCurrentThreadId();//получаем идентификатор потокf for (k = 0; k <= 4; k++) {//Ищем номер потока if (d[k] == ex ) ipex = k; } printf("Поток %d ждёт \n",ipex); 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 << "Слишком много свободных!!!\n"; } } void CloseMySemaphore(TMySemaphore *S) {//Закрываем семафор CloseHandle(S->HEvent);//Закрываем дескриптор события } DWORD proc1() {//Процедура добавляющих потоков int x, i, j, ip; HANDLE id; id = (HANDLE)GetCurrentThreadId();//получаем идентификатор потока ip = 0;//Пока еще не нашли for (i = 0; i <= 4; i++) {//Ищем номер потока if (d[i] == id) ip = i; } for (i = 0; i <= 4; i++) {//Меняем пять чисел printf("Поток %d Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); WaitForMySemaphore(&Sem);//Ждем семафора Sleep(3000);//задержка(3 сек.) printf("Поток %d Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); j = rand() % 10;//[0..9] x = rand() % 100; //Пишем, какое число мы заменил cout << "Поток " << ip << " Поток#" << ip << " заменил число под номером:" << j << "-" << x << "\n"; q[j] = x;//Меняем в массиве сл. число на сл. месте Sleep(2000); ReleaseMySemaphore(&Sem);//Освоб семафор printf("Поток %d Освобождён \n", ip); printf("Поток %d - Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); } return 0; } DWORD proc2() {//процедура вынимающего потока int i, j, x, ip; LPDWORD id; id = (LPDWORD)GetCurrentThreadId();//получаем идентификатор потока ip = 0; for (i = 0; i <= 4; i++) {//Ищем номер потока if (d[i] == id) ip = i; } for (i = 0; i <= 9; i++) {//смотрим случайный элемент массива //Состояние семафора printf("Поток %d - Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); WaitForMySemaphore(&Sem);//Ждём семафора Sleep(2000); printf("Поток %d - Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); j = rand() % 10; //Место x = q[j];//Вынимаем число из массива cout << "Поток " << ip << " Поток#" << ip << " получил число из места:" << j << "-" << x << "\n"; Sleep(2000); ReleaseMySemaphore(&Sem);//Освоб. семафор printf("Поток %d Освобождён \n", ip); printf("Поток %d - Свободно в семафоре: %d Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting); } return 0; } int main() {//Основная программа setlocale(LC_ALL, "russian_russia"); srand(time(NULL)); cout << "Исходный массив:"; for (i = 0; i <= 9; i++) {//Заполняем и выводим массив q[i] = rand() % 100; cout << q[i] << " "; } cout << "\n"; CreateMySemaphore(&Sem, 1, 1, "EventSemaphore");//Созд. семафор for (i = 0; i <= 2; i++) { h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc1, NULL, 0, (LPDWORD)&d[i]);//Создаём 3 кладущих потока if (h[i] == 0) cout << (GetLastError()); Sleep(500); } Sleep(1000); for (i = 3; i <= 4; i++) { h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc2, NULL, 0, (LPDWORD)&d[i]);//Создаём 2 вынимающих потока dwError = GetLastError(); if (h[i] == 0) cout << (dwError); Sleep(500); } WaitForMultipleObjects(5, &h[0], true, INFINITE);//Ждём завершения всех потоков for (i = 0; i <= 4; i++) { CloseHandle(h[i]);//Закрываем дескрипторы потоков } CloseMySemaphore(&Sem);//Закрываем семафор cout << "Полученный массив:"; //то, что получилось for (i = 0; i <= 9; i++) { //Выводим массив cout << q[i] << " "; } fflush(stdout); _getch(); return 0; }