Шаг 116 - EnterCriticalSection, LeaveCriticalSection и InitializeCriticalSection.
Очень полезно сначала прочитать "Шаг 80 - Что такое критическая секция (Critical Section)", так как именно эти функции относятся к критической секции. Давайте посмотрим пример. Следующий код выполянет ряд действий над массивом.
// TestCritical.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#define MAX_ARRAY 5
int array[MAX_ARRAY];
void EmptyArray();
void PrintArray();
void FullArray();
void main()
{
EmptyArray();
PrintArray();
FullArray();
PrintArray();
EmptyArray();
PrintArray();
}
void EmptyArray()
{
for (int x=0;x<(MAX_ARRAY+1); x++) array[x]=0;
Sleep(1000);
}
void PrintArray()
{
for (int x=0;x<(MAX_ARRAY+1); x++) cout << array[x] << " ";
cout << endl;
Sleep(1000);
}
void FullArray()
{
for (int x=0;x<(MAX_ARRAY+1); x++) array[x]=x;
Sleep(1000);
}
В данном примере все нормально. У нас всего один поток. Этот поток последовательно выполнит все действия над распределенным объектом array. Почему он распределенный ? Потому, что он определен глобально и к нему можно обратиться в любой момент. Так вот, если у нас будет несколько потоков все станет сложнее. Одна фунция не успеет очистить массив, а вторая может уже начать писать или печатать не до конца очищенный массив. Вот для решения этих проблем и используются критические секции. В тот код, который правит распределенный ресурс и является критической секцией. Для объявления начала критической секции используется функция.
VOID EnterCriticalSection
(
LPCRITICAL_SECTION lpCriticalSection // указатель на переменную критическая секция.
);
А для выхода из критической секции.
VOID LeaveCriticalSection
(
LPCRITICAL_SECTION lpCriticalSection // указатель на переменную критическая секция.
);
Для работы с критической секцией нам нужна переменная типа - критическай секция. Вот она.
CRITICAL_SECTION
Перед тем как использовать критическую секцию ее надо проинициализировать.
VOID InitializeCriticalSection
(
LPCRITICAL_SECTION lpCriticalSection // указатель на переменную критическая секция.
);
// TestCritical.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "process.h"
#define MAX_ARRAY 5
CRITICAL_SECTION critsect;
int array[MAX_ARRAY];
void EmptyArray(void *);
void PrintArray(void *);
void FullArray(void *);
void main()
{
InitializeCriticalSection(&critsect);
if (_beginthread(EmptyArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
if (_beginthread(PrintArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
if (_beginthread(FullArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
if (_beginthread(PrintArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
if (_beginthread(EmptyArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
if (_beginthread(PrintArray,1024,NULL)==-1) cout << "Error begin thread " << endl;
Sleep(10000);
}
void EmptyArray(void *)
{
cout << "EmptyArray" << endl;
EnterCriticalSection(&critsect);
for (int x=0;x<(MAX_ARRAY+1); x++) array[x]=0;
Sleep(1000);
LeaveCriticalSection(&critsect);
_endthread();
}
void PrintArray(void *)
{
cout << "PrintArray" << endl;
EnterCriticalSection(&critsect);
for (int x=0;x<(MAX_ARRAY+1); x++) cout << array[x] << " ";
cout << endl;
Sleep(1000);
LeaveCriticalSection(&critsect);
_endthread();
}
void FullArray(void *)
{
cout << "FullArray" <<
endl;
EnterCriticalSection(&critsect);
for (int x=0;x<(MAX_ARRAY+1); x++) array[x]=x;
Sleep(1000);
LeaveCriticalSection(&critsect);
_endthread();
}
Результат работы будет вот такой.
EmptyArray
PrintArray
FullArray
PrintArray
EmptyArray
PrintArray
0 0 0 0 0 0
0 1 2 3 4 5
0 0 0 0 0 0
Потоки запускаются, начинается доступ к критичекой секции. Дожидаются своей очереди и выполняют необходимые действия. Не забудьте установиь опции многопоточного проекта, как в шаге ActiveX: "Шаг 78 - Что понимается под условиям гонки (rase condition)".
Предыдущий Шаг | Следующий Шаг | Оглавление
By Artem.
Используются технологии uCoz
|