Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Лекция №8. Особенности: volatile BOOL g_fFinished = FALSE;




 

Особенности:

  • volatile BOOL g_fFinished = FALSE;

/*volatile – загружаем значение из памяти при каждом обращении к переменной (отключает оптимизации компилятора).*/

 

int main() {

CreateThread (…, CalcFunc,…);

While (g_fFinished = = FALSE);

}

DWORD WINAPI CalcFunc (PVOID) {

g_fFinished = TRUE;

}

 

Если не будем использовать ключевое слово volatile, то возникнет риск того, что значения флага загрузятся в регистр процессора перед вычислением while, и в дальнейшем проверяться будет значение из регистра, т.е. ждущий процесс никогда не увидит окончания вычислений.

  • Thr1 Thr2

 
 

 


При реализации спин-блокировки возможна ситуация, когда поток длительное время опрашивает условие входа E, периодически это условие оказывается истинным, тем не менее, поток не может войти в критический участок. Происходит «отталкивание» (starvation, голодание). Можно решить, добавив Sleep(0) в конец Thr1.

 

  • Влияние КЭШ-линий.

volatile int x = 0; // Thread1() x++

volatile int y = 0; // Thread2() y++

Для ускорения работы с ОЗУ каждый из процессоров использует локальный КЭШ, однако подгрузка в КЭШ производится не побайтно, а загружается целиком КЭШ-линия (участок памяти, выровненный по 32-байтной границе). Если две переменные попадают в одну КЭШ-линию, то эффект от использования КЭШа пропадает: нужно обновлять данные и в ОЗУ и во втором КЭШе. Поэтому следует выровнять переменные по границам КЭШ-линии или вводить фиктивные переменные, чтобы гарантировать, что переменные не попадут в одну КЭШ-линию. Для того чтобы избежать этих проблем, в Windows реализован такой объект, как критическая секция.

 

Критическая Секция Windows

void InitializeCriticalSection (PCritical_Section);

void DeleteCriticalSection();

void EnterCriticalSection();

bool TryEnterCriticalSection();

void LeaveCriticalSection();

bool InitializeCriticalSectionAndCount();

setCriticalSectionSpinCount();

 

Достоинство: высокое быстродействие.

Недостатки: interlocked функции не переводят поток в режиме ожидания, нельзя указать тайм-аут, нельзя использовать при межпроцессном взаимодействии.

 

Синхронизация в режиме ядра

Для такой синхронизации используются объекты ядра, которые могут находиться в сигнальном (свободном) и несигнальном (занятом) состоянии.

Это – процессы, потоки, задания, файлы, консольный ввод, уведомления об изменении файлов, события, ожидаемые таймеры, мьютексы, семафоры.

WaitForSingleObject(HANDLE, DWORD dwMultiSec);

WaitForMultipleObject(…, BOOL fWaitAll, …);

Если происходит переход объект в сигнальное состояние в момент блокировки, то обычно происходит снятие блокировки, и выполняются некоторые действия, зависящие от объекта ядра.

Возвращают:

- В случае завершения тайм-аута: WAIT_TIMEOUT;

- В случае ошибки: WAIT_FAILED;

- “Указатель” на следующий в порядке ожидания объект: WAIT_OBJECT_0;

Чтобы узнать, какой именно объект перешел в сигнальное состояние, проверяем, что значение не равно WAIT_FAILED и WAIT_TIMEOUT и вычитаем из него WAIT_OBJECT_0 и получаем индекс в массиве, переданном в WaitForMultipleObject().

 

Управление объектами ядра

Создание CreateMutex()

Закрытие BOOL CloseHandle(HANDLE)

Каждый процесс имеет таблицу описателей:

При закрытии HANDLE мы удаляем описатель из таблицы и декрементируем счетчик i. Если i = 0 – уничтожение объекта.

Наследование: SECURITY_ATTRIBUTE sa;

sa.nlength = sizeof(sa);

sa.lpSecurityDescriptor=NULL; /*NULL – защита по умолчанию; определяет, кто может пользоваться объектом (при NULL – создатель процесса и администраторы) */

sa.bInHeritHandle=TRUE; /*наследовать HANDLE*/

HANDLE hMutex = CreateMutex (&sa, FALSE, NULL);

 

 

Для передачи описателя в дочерний процесс обычно используется командная строка или переменные окружения.

Если объект создается уже после создания дочернего процесса, то дочерний процесс не содержит наследованного описателя.

 




Поделиться с друзьями:


Дата добавления: 2014-12-07; Просмотров: 387; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.011 сек.