Реферат: Критические секции

} m_data;

void Proc1(SData& data)

{

m_data = data;

}

и все бы хорошо, если бы у структуры SData был конструктор копирования, например такой:

SData(const SData data)

{

CScopeLock lock(data.m_lock);

m_dwSmth = data.m_dwSmth;

}

Но нет, программист посчитал, что хватит за глаза простого копирования полей, и, в результате, переменная m_lock была просто скопирована, хотя именно в этот момент из другой нити она была "захвачена", и значение поля LockCount у нее в этот момент больше либо равно нулю. После вызова ::LeaveCriticalSection() в той нити, у исходной переменной m_lock значение поля LockCount уменьшилось на единицу. А у скопированной переменной – осталось прежним. И любой вызов ::EnterCriticalSection() в этой нити никогда не вернется. Он будет вечно ждать неизвестно чего.

Это только цветочки. С ягодками вы очень быстро столкнетесь, если попытаетесь написать что-нибудь действительно сложное. Например, ActiveX-объект в многопоточном подразделении (MTA), создаваемый из скрипта, запущенного из-под контейнера, размещенного в однопоточном подразделении (STA). Ни слова не понятно? Не беда. Сейчас я попытаюсь выразить проблему более понятным языком. Итак. Имеется объект, вызывающий методы другого объекта, причем живут они в разных нитях. Вызовы производятся синхронно. Т.е. объект №1 переключает выполнение на нить объекта №2, вызывает метод и переключается обратно на свою нить. При этом выполнение нити №1 приостановлено до тех пор, пока не отработает нить объекта №2. Теперь, положим, объект №2 вызывает метод объекта №1 из своей нити. Получается, что управление вернулось в объект №1, но из нити объекта №2. Если объект №1 вызывал метод объекта №2, захватив какую-либо критическую секцию, то при вызове метода объекта №1 тот заблокирует сам себя при повторном входе в ту же критическую секцию.

Листинг 11. Самоблокировка средствами одного объекта.

// Нить №1

void IObject1::Proc1()

{

// Входим в критическую секцию объекта №1

m_lockObject.Lock();

// Вызываем метод объекта №2, происходит переключение на нить объекта №2

m_pObject2->SomeMethod();

// Сюда мы попадем только по возвращении из m_pObject2->SomeMethod()

m_lockObject.Unlock();

}

// Нить №2

void IObject2::SomeMethod()

{

// Вызываем метод объекта №1 из нити объекта №2

m_pObject1->Proc2();

К-во Просмотров: 764
Бесплатно скачать Реферат: Критические секции