Лекция № 12 Синхронизация потоков с использованием объектов ядра — КиберПедия 

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Лекция № 12 Синхронизация потоков с использованием объектов ядра

2017-06-19 344
Лекция № 12 Синхронизация потоков с использованием объектов ядра 0.00 из 5.00 0 оценок
Заказать работу

Задачу синхронизации потоков различных процессов принято решать с помощью объектов ядра. Объекту ядра может быть присвоено имя, они позволяют задавать тайм-аут для времени ожидания и обладают еще рядом возможностей для реализации гибких сценариев синхронизации.

Почти все объекты ядра, рассмотренные ранее, в том числе, процессы, потоки и файлы, пригодны для решения задач синхронизации. В контексте задач синхронизации о каждом из объектов можно сказать, находится ли он в свободном (сигнальном, signaled state) или занятом (nonsignaled state) состоянии. Правила перехода объекта из одного состояния в другое зависят от объекта. Например, если поток выполняется, то он находится в занятом состоянии, а если поток успешно завершил ожидание семафора, то семафор находится в занятом состоянии.

Потоки находятся в состоянии ожидания, пока ожидаемые ими объекты заняты. Как только объект освобождается, ОС будит поток и позволяет продолжить выполнение. Для приостановки потока и перевода его в состояние ожидания/освобождения объекта используется функция

DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);

где hObject - описатель ожидаемого объекта ядра, а второй параметр - максимальное время ожидания объекта.

Поток создает объект ядра при помощи семейства функций Create (CreateSemaphore, CreateThread и т.д.), после чего объект посредством описателя становится доступным всем потокам данного процесса. Копия описателя может быть получена при помощи функции DuplicateHandle и передана другому процессу, после чего потоки смогут воспользоваться этим объектом для синхронизации.

Другим, более распространенным способом получения описателя является открытие существующего объекта по имени, поскольку многие объекты имеют имена в пространстве имен объектов. Имя объекта - один из параметров Create -функций. Зная имя объекта, поток, обладающий нужными правами доступа, получает его описатель с помощью Open -функций. Напомним, что в структуре, описывающей объект, имеется счетчик ссылок на него, который увеличивается на 1 при открытии объекта и уменьшается на 1 при его закрытии.

Рассмотрим те объекты ядра, которые предназначены непосредственно для решения проблем синхронизации.

Объекты Mutex-ы

Свое название объекты получили от выражения “mutually exclusive”, что означает “взаимно исключающий”. Объект Mutex может находится в отмеченном или неотмеченном состоянии. Когда какая-либо задача, принадлежащая любому процессу, становится владельцем объекта Mutex, последний переключается в неотмеченное состояние. Если же задача “отказывается” от владения объектом Mutex, его состояние становится отмеченным.

В каждый момент только одна задача может владеть mutex-ом. Все остальные задачи для того чтобы завладеть объектом, который уже захвачен, должны ждать, например, с помощью уже известных вам функции WaitForSingleObject.

Для создания объекта Mutex используется функция CreateMutex, прототип которой приведен ниже:

 

 

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexAttributes, // атрибуты защиты

BOOL bInitialOwner, // начальное состояние

LPCTSTR lpName); // имя объекта Mutex

В качестве первого параметра (атрибуты защиты) можно указать значение NULL.

Параметр bInitialOwner определяет начальное состояние объекта Mutex. Если он имеет значение TRUE, задача, создающая объект Mutex, будет им владеть сразу после создания. Если же значение этого параметра равно FALSE, после создания объект Mutex не будет принадлежать ни одной задаче, пока не будет захвачен ими явным образом.

Через параметр lpName передается указатель на имя объекта Mutex. Если объект Mutex будет использован только задачами одного процесса, вместо адреса имени можно указать значение NULL. В этом случае будет создан “безымянный” объект Mutex.

Функция CreateMutex возвращает идентификатор созданного объекта Mutex или NULL при ошибке.

Объекты Семафоры

Объект Семафор это развитие объекта mutex.

Известно, что семафоры, предложенные Дейкстрой в 1965 г., представляет собой целую переменную, доступ к которой, после ее инициализации, может осуществляться через две операции: wait и signal (в ОС Windows это функции WaitForSingleObject и ReleaseSemaphore соответственно).

wait(S): если S <= 0 процесс блокируется

(переводится в состояние ожидания);

в противном случае S = S - 1;

signal(S): S = S + 1

Семафоры обычно используются для учета ресурсов (текущее число ресурсов задается переменной S) и создаются при помощи функции CreateSemaphore, в число параметров которой входят начальное и максимальное значение переменной. Текущее значение не может быть больше максимального и отрицательным. Значение S, равное нулю, означает, что семафор занят.

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // атрибуты защиты

LONG lInitialCount, // начальное значение счетчика семафора S

LONG lMaximumCount, // максимальное значение S счетчика семафора

LPCTSTR lpName); // адрес строки с именем семафора

Для увеличения значения счетчика семафора приложение должно использовать функцию ReleaseSemaphore:

BOOL ReleaseSemaphore(

HANDLE hSemaphore, // идентификатор семафора

LONG cReleaseCount, // значение инкремента

LPLONG lplPreviousCount); // адрес переменной для предыдущего счетчика семафора

Функция ReleaseSemaphore увеличивает значение счетчика семафора, идентификатор которого передается ей через параметр hSemaphore, на значение, указанное в параметре cReleaseCount.

Ниже приведен пример синхронизации программы с помощью семафоров.

//Практическое занятие № 27

//Группа xxxxxx Терминал N ФИО

#include "stdafx.h"

#include "windows.h" // win32 API

#include <locale.h> // подключение Русского языка

#include <iostream> // инструкции c++ std,cout,cin …

using namespace std; // пространство стандартных имен */

int Sum = 0, iNumber=5, jNumber=300000;

HANDLE hFirstSemaphore, hSecondSemaphore;

DWORD WINAPI SecondThread(LPVOID)

{

int i,j;

double a,b=1.;

for (i = 0; i < iNumber; i++)

{

WaitForSingleObject(hSecondSemaphore, INFINITE);

for (j = 0; j < jNumber; j++)

{

Sum = Sum + 1; a=sin(b);

}

ReleaseSemaphore(hFirstSemaphore, 1, NULL);

}

return 0;

}

Void main()

{

int i,j;

HANDLE hThread;

DWORD IDThread;

double a,b=1.;

hFirstSemaphore=CreateSemaphore(NULL,0,1, (LPCWSTR)"MyFirstSemaphore");

hSecondSemaphore=CreateSemaphore(NULL,1,1, (LPCWSTR)"MySecondSemaphore");

hThread=CreateThread(NULL, 0, SecondThread, NULL, 0, &IDThread);

if (hThread == NULL) return;

for (i = 0; i < iNumber; i++)

{

WaitForSingleObject(hFirstSemaphore, INFINITE);

for (j = 0; j < jNumber; j++)

{

Sum = Sum - 1; a=sin(b);

}

cout<<"Sum= "<<Sum<<endl;

ReleaseSemaphore(hSecondSemaphore, 1, NULL);

}


Поделиться с друзьями:

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.017 с.