Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...
История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...
Топ:
Генеалогическое древо Султанов Османской империи: Османские правители, вначале, будучи еще бейлербеями Анатолии, женились на дочерях византийских императоров...
Особенности труда и отдыха в условиях низких температур: К работам при низких температурах на открытом воздухе и в не отапливаемых помещениях допускаются лица не моложе 18 лет, прошедшие...
Техника безопасности при работе на пароконвектомате: К обслуживанию пароконвектомата допускаются лица, прошедшие технический минимум по эксплуатации оборудования...
Интересное:
Искусственное повышение поверхности территории: Варианты искусственного повышения поверхности территории необходимо выбирать на основе анализа следующих характеристик защищаемой территории...
Распространение рака на другие отдаленные от желудка органы: Характерных симптомов рака желудка не существует. Выраженные симптомы появляются, когда опухоль...
Лечение прогрессирующих форм рака: Одним из наиболее важных достижений экспериментальной химиотерапии опухолей, начатой в 60-х и реализованной в 70-х годах, является...
Дисциплины:
2017-06-11 | 492 |
5.00
из
|
Заказать работу |
Содержание книги
Поиск на нашем сайте
|
|
Входящее в состав Win32 API семейство выполняющихся атомарно Interlocked-функций дает ключ к решению многих проблем синхронизации. Например, функция
LONG InterlockedExchangeAdd(PLONG plAddend, LONG lncrement);
позволяет атомарным образом увеличить значение переменной. В этом случае корректное приращение переменной Count, описанное в начале лекции, может быть обеспечено следующей операцией:
InterlockedExchangeAdd (&Count, 1);
В MSDN можно прочитать и про другие Interlocked-функции. Например, в качестве TSL инструкции, необходимой для решения проблемы входа в критическую секцию, можно применить функцию InterlockedCompareExchange.
Реализация Interlocked-функций зависит от аппаратной платформы. На x86-процессорах они выдают по шине аппаратный сигнал, закрывая для других процессоров конкретный адрес памяти.
Существенно то, что Interlocked-функции выполняются в пользовательском режиме работы процессора в течение примерно 50 тактов, то есть чрезвычайно быстро.
Прогон программы синхронизации с помощью переменной замка
Для практического знакомства с проблемой синхронизации вначале необходимо написать программу, требующую синхронизации. Например, такую, как приведенная ниже программа async:
#include <windows.h>
#include <stdio.h>
#include <math.h>
int Sum = 0, iNumber=5, jNumber=300000;
DWORD WINAPI SecondThread(LPVOID){
int i,j;
double a,b=1.;
for (i = 0; i < iNumber; i++)
{
for (j = 0; j < jNumber; j++)
{
Sum = Sum + 1; a=sin(b);
}
}
return 0;
}
void main(){
int i,j;
double a,b=1.;
HANDLE hThread;
DWORD IDThread;
hThread=CreateThread(NULL, 0, SecondThread, NULL, 0, &IDThread);
if (hThread == NULL) return;
for (i = 0; i < iNumber; i++)
{
for (j = 0; j < jNumber; j++)
{
Sum = Sum - 1; a=sin(b);
}
printf(" %d ",Sum);
}
WaitForSingleObject(hThread, INFINITE); // ожидание окончания потока SecondThread
printf(" %d ",Sum);
}
В данной программе поток SecondThread в цикле дает приращение общей переменной Sum, а основной поток также в цикле уменьшает ее значение и периодически выводит его на экран. Вычисление синуса включено в программу для замедления. Легко убедиться, что результаты работы программы вследствие перемешивания непредсказуемы, особенно если параметр jNumber подобрать с учетом быстродействия компьютера.
|
Рекомендуется ввести в данную программу синхронизацию с помощью глобальной переменной-замка, включив в нее операции while(lock); и lock=1; и добиться предсказуемости в работе программы.
Поскольку ситуация, в которой квант времени, выделенный потоку, истекает между while(lock); и lock=1; маловероятна, можно смоделировать ее искусственно, введя между этими операциями паузу (функция Sleep, например). Наконец, желательно реализовать правильное решение путем опроса и модификации переменной замка с помощью TSL-инструкции (функция InterlockedCompareExchange).
Спин-блокировка
Рассмотренные решения проблемы синхронизации, безусловно, являются корректными. Они реализуют следующий алгоритм: перед входом в критическую секцию поток проверяет возможность входа и, если такой возможности нет, продолжает опрос значения переменной-замка. Такое поведение потока, связанное с его вращением в пустом цикле, называется активным ожиданием или спин-блокировкой (spin lock).
Очевидно, что на однопроцессорной машине это пустая трата машинного времени, поскольку значение опрашиваемой переменной в течение этого цикла не может быть волшебным образом изменено.
Спин-блокировка, хотя бы временная, может быть полезна на многопроцессорных машинах, где один из потоков крутится в цикле, а второй - работает на другом процессоре и может изменить значение переменной-замка. В этом случае у активно ожидающего потока есть шанс быстро войти в критическую секцию, не будучи блокированным. Блокировка потока связана с переходом в режим ядра (примерно 1000 тактов работы процессора).
Однако более разумным решением, особенно на однопроцессорных машинах, представляется перевод потока в состояние ожидания, если вход в критическую секцию запрещен. После снятия запрета на вход в критическую секцию этот поток переводится в состояние готовности.
|
Critical Sections
В составе API ОС Windows имеются специальные и эффективные функции для организации входа в критическую секцию и выхода из нее потоков одного процесса в режиме пользователя. Они называются EnterCriticalSection и LeaveCriticalSection и имеют в качестве параметра предварительно проинициализированную структуру типа CRITICAL_SECTION.
Примерная схема программы может выглядеть следующим образом.
CRITICAL_SECTION cs;
DWORD WINAPI SecondThread()
{
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
… критический участок кода
LeaveCriticalSection(&cs);
}
main ()
{
InitializeCriticalSection(&cs);
CreateThread(NULL, 0, SecondThread,…);
EnterCriticalSection(&cs);
… критический участок кода
LeaveCriticalSecLion(&cs);
DeleteCriticalSection(&cs);
}
Функции EnterCriticalSection и LeaveCriticalSection реализованы на основе Interlocked-функций, выполняются атомарным образом и работают очень быстро. Существенным является то, что в случае невозможности входа в критический участок поток переходит в состояние ожидания. Впоследствии, когда такая возможность появится, поток будет "разбужен" и сможет сделать попытку входа в критическую секцию. Механизм пробуждения потока реализован с помощью объекта ядра "событие" (event), которое создается только в случае возникновения конфликтной ситуации.
Уже говорилось, что иногда, перед блокированием потока, имеет смысл некоторое время удерживать его в состоянии активного ожидания. Чтобы функция EnterCriticalSection выполняла заданное число циклов спин-блокировки, критическую секцию целесообразно проинициализировать с помощью функции InitalizeCriticalSectionAndSpinCount.
Прогон программы
В качестве самостоятельного упражнения рекомендуется реализовать синхронизацию в выше приведенной программе async с помощью перечисленных примитивов. Важно не забывать про корректный выход из критической секции, то есть про парное использование функций EnterCriticalSection и LeaveCriticalSection.
|
|
Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...
Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...
Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...
Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!