Необходимо реализовать синхронизацию двух потоков, которые инициализируют массив целых чисел. Этот массив будет разделяемым ресурсом. В качестве средства синхронизации нужно использовать симафор.
Решение поставленной задачи.
Для демонстрации работы семафора используем в качестве потоков, зависящие от времени потоки. Пусть это будет гонка двух потоков, скорость выполнения которых будет зависеть от задержки, генерируемой случайным образом. Для удобства демонстрации примем предел одной задержки равный 1 секунде, а количество задержек равным 10. В качестве разделяемого ресурса используем массив двадцати целых чисел.
static DWORD WINAPI FirstThread(void *pv) { COORD pos; // Переменная, которая будет хранить текущую координату курсора pos.X=3; // Столбец отображения задерки первого потока BOOL fDone=FALSE; // Флаг отработки потокаwhile (!fDone) { ::WaitForSingleObject(&g_hSemaphore, INFINITE); // Ожидание запуска семафора на длительном интервале времениif(g_nIndex>=MaxCount) // Проверяю, не создано ли потоков больше чем максимальное кол-во потоков fDone=TRUE; else { g_nIndex++; // Количество потоков увеличиваю на 1for (int i=0; i<=10; i++) // Начинаю цикл для инициализации массива 10 временных задержек { srand(time(NULL)); // Включаю генератор случайных чисел IndexResours++; a[IndexResours-1]= rand()%1000; // Генерирую задержку первого потока (от 0 до 1000 миллисекунд) pos.Y = i; SetConsoleCursorPosition (hStdout ,pos); // Устанавливаю курсор в i - тую строку printf("%d", a[IndexResours-1]); // Вывожу текущую задержку для первого потока Sleep(a[IndexResours-1]); // Осуществляю задерку на текущее количество миллисекунд } } ::ReleaseSemaphore(g_hSemaphore,1,0); // Освобождаю семафор от данного потока } if (!Lid) // Если лидирующий поток не определён, то делаю данный лидирующим Lid = 1; return 0;}
static DWORD WINAPI SecondThread(void *pv) { COORD pos; // Переменная, которая будет хранить текущую координату курсораint Speed2[10]; // Массив задержек второго потока pos.X=25; // Столбец отображения задерки второго потока BOOL fDone=FALSE; // Флаг отработки потокаwhile (!fDone) { ::WaitForSingleObject(&g_hSemaphore, INFINITE); // Ожидание запуска семафора на длительном интервале времениif(g_nIndex>=MaxCount) // Проверяю, не создано ли потоков больше чем максимальное кол-во потоков fDone=TRUE; else { g_nIndex++; // Количество потоков увеличиваю на 1for (int i=0; i<=10; i++) // Начинаю цикл для инициализации массива 10-ти временных задержек { IndexResours++; a[IndexResours-1]= rand()%1000; // Генерирую задержку второго потока (от 0 до 1000 миллисекунд) pos.Y = i; SetConsoleCursorPosition (hStdout ,pos); // Устанавливаю курсор в i - тую строку printf("%d", a[IndexResours-1]); // Вывожу текущую задержку для второго потока Sleep(a[IndexResours-1]); // Осуществляю задерку на текущее количество миллисекунд } } ::ReleaseSemaphore(g_hSemaphore,1,0); // Освобождаю семафор от данного потока } if (!Lid) // Если лидирующий поток не определён, то делаю данный лидирующим Lid = 2; return 0;}
Из листингов потоков видно, что скорость их выполнения зависит от времени. Далее представлено основное тело программы, в котором организована синхронизация потоков с использованием Семафора.
// Semaphore.cpp : Defines the entry point for the console application.//#include"stdafx.h"#include"Semaphore.h"#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <windows.h>#ifdef _DEBUG#definenew DEBUG_NEW#undef THIS_FILEstaticchar THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// The one and only application objectCWinApp theApp;usingnamespace std;static DWORD WINAPI FirstThread(void *pv); // Прототипы функций,static DWORD WINAPI SecondThread(void *pv); // которые будут участвовать в <гонке designtimesp=21150> потоков.HANDLE g_hSemaphore; // Обьявляем Хендл семафора,HANDLE hStdout; // Хендл вывода информации в консоли,int Lid=0, g_nIndex=0; // Флаг, определяющий поток завершённый первым(лидерство), количество синхронизируемых потоков,int a[20], IndexResours=0; // Общий ресурс и его индексLONG MaxCount = 2; // Максимальное количество синхронизируемых семафором потоков.int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ int nRetCode = 0; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // initialize MFC and print and error on failureif (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T("Fatal Error: MFC initialization failed") << endl; nRetCode = 1; } else { // TODO: code your application's behavior here. DWORD dw; // Обьект синхронизации LONG g_iCount = 0; // начальное значение семафора HANDLE hThreads[2]; // Массив Хендлов потоков g_hSemaphore = ::CreateSemaphore(NULL, g_iCount, MaxCount, NULL); // Создаем семафор и инициализируем его Хендл hThreads[0] = ::CreateThread(NULL, 0, FirstThread, NULL, 0 , &dw); // Создаем потоки hThreads[1] = ::CreateThread(NULL, 0, SecondThread, NULL, 0 , &dw); // и инициализируем Массив Хендлов потоков ::ResumeThread(hThreads[0]); //Запускаем потоки ::ResumeThread(hThreads[1]); ::WaitForMultipleObjects(2, hThreads, TRUE, INFINITE); // Ожидаем окончание работы 2 потоков // на очень длительном интервале времени ::CloseHandle(hThreads[0]); // Закрываем созданные потоки ::CloseHandle(hThreads[1]); ::CloseHandle(g_hSemaphore); // и сам семафорswitch (Lid) //определяем поток, который завершился первым { case 1 : cout << "n nepBbIu' noTok *I*uHuLLIupoBaJI nepBbIM!!!n"; break; case 2 : cout << "n BTopou' noTok *I*uHuLLIupoBaJI nepBbIM!!!n"; break; default : break; } // и выводим информацию о номере этого потока } cout << endl << "The END!!!" << endl << "Press Any Key..."; // Выводим информацию о завершении работы программы getch(); // ожидание нажатия клавиши для окончания работыreturn nRetCode;}
Результат возможной работы программы
Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.