C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 116 - EnterCriticalSection, LeaveCriticalSection и InitializeCriticalSection / Win 32 API / Win32 API

Шаг 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) ?".


| |
Автор Каев Артем.
[AD]