- •Лабораторная работа № 3. Синхронизация потоков с использованием мfс
- •Задача синхронизации потоков
- •Создание и синхронизация потоков с использованием mfc
- •1. Синхронизация с использованием глобальной переменной
- •3. Взаимодействие с помощью объектов событий
- •1. Критические секции.
- •2. Мьютексы.
- •3. Семафор
- •Создание и выполнение потоков
- •Функция WaitForSingleObject
- •Cинхронизация в mfc
- •Cинхронизация в cMutex
- •Задания для самостоятельного выполнения.
3. Семафор
Использование этого объекта ничем не отличается от использования предыдущих. Разница заключается в том, что семафор дает право на использование контролируемых параметров определенному числу потоков. В семафоре хранится количество объектов, которые в данный момент имеют доступ к данным.
CSemaphore semaphore(2,2); //создание семафора. При создании семафора указывается начальное и максимальное значение счетчика
CSingleLock sLock(&semaphore); //Захват семафора
sLock.Lock();
При вызове метода Lock() значение счетчика внутри семафора уменьшается. Когда оно достигнет нуля, метод Lock() будет ждать освобождения семафора. После этого захватит семафор и вернет управление вызывающей функции
sLock.Unlock(); //Освобождение семафора
Пример 1. Рассмотрим консольное приложение, организующее взаимодействие двух потоков, которые задаются попеременным захватом и освобождением мьютексов 1 и 2. Команда cout.flush()переводит строки в поток, предварительно очищая буфер. Общее время обозначено SumTime. Приложение работает до тех пор, пока SumTime < 10000 мкс. Если проект не запускается, то необходимо выполнить следующую последовательность действий:
Проект -> свойства: (самая нижняя строка)-> раскрываем вкладку свойства конфигурации-> Общие. Справа в графе " набор символов" выбираем параметр "не задано"
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include <string>
#include <conio.h>
#include <stdio.h>
using namespace std;
int SumTime;
void KeepMutex(HANDLE mutex,int Time); // заголовок функции KeepMutex
void main()
{
int i;
DWORD res;
// создаем объекты-взаимоисключения
HANDLE mutex1 = CreateMutex(NULL, FALSE, "APPNAME-MTX01");
HANDLE mutex2 = CreateMutex(NULL, FALSE, "APPNAME-MTX01");
srand ((unsigned) time (NULL));// установка псевдослучайного генератораж
// в течение 10 секунд пытаемся попеременно захватывать объекты mutex1 и mutex2
while (SumTime<10000){
cout<<"Trying to get mutex1\n"; cout.flush();//
res = WaitForSingleObject(mutex2,3000);
if (res == WAIT_OBJECT_0) // если захват удался
{KeepMutex(mutex1,1000);}; //вызов функции, эмулирующей захват объекта
cout<<"Trying to get mutex2\n"; cout.flush();
res = WaitForSingleObject(mutex1,20000);
if (res == WAIT_OBJECT_0) // если захват удался
{KeepMutex(mutex2,2000);};
cout<<"SumTime="<<SumTime<<"\n\n";
};
cout<<"FINISH!!";
CloseHandle(mutex1);// закрываем дескрипторы
CloseHandle(mutex2);
system("pause");//запрос на завершение работы приложения
};
void KeepMutex(HANDLE mutex,int Time)
{
int T;
T=rand()*Time/(RAND_MAX+1);//расчет текущего времени ожидания
Sleep(T); // ждем
cout<<"Got it! Waiting for mutex"<<"Time="<<T<<"\n"; cout.flush();
cout<<"Now releasing the mutex"<<"\n"; cout.flush();// освобождаем объект
ReleaseMutex(mutex);
SumTime+=T; //пересчет общего времени
}
Задания:
Модифицировать текст программы таким образом, чтобы в ней использовались 3 мьютекса, которые бы удерживали процесс в порядке 1-2-3-1-…
Сократить число мьютексов до одного.
Добавить печать суммарного времени для каждого обработки мьютекса.
