Реферат: Критические секции
} 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
Бесплатно скачать Реферат: Критические секции
|