Многопоточность в приложениях. Разработка приложения, иллюстрирующего работу семафоров, страница 2

Событие  - условие, выполнение которого должно или может вызывать определенную реакцию программы или ОС (например, получение сообщения, завершения обмена, выдача сигнала). Иными словами событие – возникновение или завершение в вычислительной системе некоторого действия. Так что событие – понятие довольно абстрактное, под ним может пониматься, например объект ядра в Windows, используемый для синхронизации потоков; в OLE под ним понимается уведомление пересылаемое от одного объекта другому или от управляющего элемента контейнеру, в ответ на изменение состояния  или действие пользователя. Под событием подразумевается любое действие пользователя которое может быть обработано программой.

Более подробно остановимся на СЕМАФОРАХ, т.к. это тема данной лабораторной работы.

Семафор – одно из средств синхронизации в многопоточных процессах, используемое для управления доступом к разделяемым ресурсам. В сущности, это тип данных, обеспечивающий средства низкого уровня для синхронизации параллельных процессов. Обычно значением семафора является целое неотрицательное число. Над семафором определены две операции: операция “освободить”, увеличивающая его значение и операция  “занять” уменьшающая его значение, если оно отлично от нуля, или при нулевом значении, приостанавливающая процесс до тех пор, пока другой процесс не выполнит операцию “освободить”.  

Чтобы использовать семафор необходимо создать экземпляр  класса CSemaphore . Этот класс имеет четыре аргумента, которые можно передать конструктору класса:

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

- Имя семафора идентифицирует его для всех работающих в ОС приложений

- Класс так же использует указатель на атрибуты защиты для семафора.

В объекте CSemaphore для захвата семафора и его освобождения предусмотрены методы Lock – блокировать и Unlock – разблокировать. Если при вызове функции Lock счетчик использований семафора больше нуля, то его значение уменьшается на единицу и программа продолжает выполнение. Если счетчик использования равен 0, то функция Lock ожидает до тех пор, пока счетчик использований не увеличится, и тогда процесс получит доступ к совместному ресурсу. Увеличение счетчика производится функцией  Unlock.


Приложение

Внешний вид разработанного приложения:

Основные функции.

Функция создает пять элементов ProgressBar и пять кнопок, а так же инициализирует семафор

void CL3View::CreatBar()

{

m_Bar1.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(20,40,250,80),this,IDC_PBar1);

m_Bar1.SetRange(1,100);

m_Bar1.SetStep(10);

m_Bar1.SetPos(0);

m_Bar2.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(20,90,250,130),this,IDC_PBar2);

m_Bar2.SetRange(1,100);

m_Bar2.SetStep(10);

m_Bar2.SetPos(0);

m_Bar3.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(20,140,250,180),this,IDC_PBar3);

m_Bar3.SetRange(1,100);

m_Bar3.SetStep(10);

m_Bar3.SetPos(0);

m_Bar4.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(20,190,250,230),this,IDC_PBar4);

m_Bar4.SetRange(1,100);

m_Bar4.SetStep(10);

m_Bar4.SetPos(0);

m_Bar5.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(20,240,250,280),this,IDC_PBar5);

m_Bar5.SetRange(1,100);

m_Bar5.SetStep(10);

m_Bar5.SetPos(0);

m_But1.Create("Поток1",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(270,40,340,80),

this,IDC_BUT1);

m_But2.Create("Поток2",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(270,90,340,130),

this,IDC_BUT2);

m_But3.Create("Поток3",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(270,140,340,180),

this,IDC_BUT3);

m_But4.Create("Поток4",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(270,190,340,230),

this,IDC_BUT4);

m_But5.Create("Поток5",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(270,240,340,280),

this,IDC_BUT5);

semaphore = new CSemaphore(3,3);

}

Функция – главная для вызываемого потока (остальные 4 аналогичны)

UINT ThreadProc1(LPVOID param)

{

SomeResource();

return 0;

}

Функция являющаяся общим ресурсом

void SomeResource()

{

int i;

semaphore->Lock();

switch(m_marker)

{

case 1:          for (i=0; i<10; i++)

{m_Bar1.StepIt();Sleep(1000);}

break;

case 2:          for (i=0; i<10; i++)

{m_Bar2.StepIt();Sleep(1000);}

break;                 

case 3:          for (i=0; i<10; i++)

{m_Bar3.StepIt();Sleep(1000);}

break;

case 4:          for (i=0; i<10; i++)

{m_Bar4.StepIt();Sleep(1000);}

break;

case 5:          for (i=0; i<10; i++)

{m_Bar5.StepIt();Sleep(1000);}

break;

}

semaphore->Unlock();

}

Блок создания потока (остальные 4 аналогично)

void CL3View::OnBut1()

{

m_marker=1;

HWND hWnd=GetSafeHwnd();

AfxBeginThread(ThreadProc1, hWnd);

}


Литература

1. Дэвис Чепмен “Освой самостоятельно. Visual C++.NET за 21 день”. Издательский дом «Вильямс» Москва * Санкт-Петербург * Киев. 2002г.  

2. Кэйт Грегори “Использование Visual C++ 6.0” Издательский дом «Вильямс» Москва * Санкт-Петербург * Киев. 2002г.