Клиент никогда не имеет дела непосредственно с
экземпляром класса CObject. Экземпляры класса CProxy – представляют копию
данных объекта CObject и делегируют запросы на чтение и запись переменной
value. Код получился несколько громоздким: к чему такие сложности? Я заранее
определил довольно широкий интерфейс, чтобы потом меньше исправлять. :)
Прошу обратить внимание на довольно сложный механизм
создания экземпляра CObject в функции GetObject. Обычно в программах
используется более простой код, типа:
CProxy&
CObject::GetObject(int level)
{
static CObject obj;
return obj.BeginTran(level);
}
Чем он плох? Дело в том, что если несколько потоков
попытаются одновременно вызвать функцию GetObject, конструктор класса CObject
может быть вызван более одного раза, так как компилятор (возможно, это его
ошибка) не генерирует безопасный код проверки с использованием ассемблерной
инструкции cmpxchg. Хотя вероятность возникновения такой ситуации довольно
низка, я рекомендую все же не игнорировать ее. Самое простое решение проблемы
заключается в использовании недорогого ресурса критической секции, например, так:
CProxy& CObject::GetObject(int level)
{
::EnterCriticalSection(&g_cs);
static CObject obj;
::LeaveCriticalSection(&g_cs);
return obj.BeginTran(level);
}
Однако встает вопрос: где ее инициализировать? Можно в
конструкторе глобального объекта, но если у нас будет такой же глобальный
клиент, мы не сможем гарантировать, что инициализация критической секции
произойдет раньше вызова функции GetObject. Нам нужно что-то, что создается, инициализируется и захватывает ресурс непосредственно в функции GetObject. В
качестве этого «чего-то» я выбрал объект исполнительной системы «Мьютекс». Его
использование вы и можете наблюдать в первоначальном коде.
Рекомендуем скачать другие рефераты по теме: решебник по физике, украинские рефераты.