Критические секции

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

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

С учетом смылса критической секции последнее кажется вполне логичным. :unsure:
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

Э... Это зависит от того, что ты понимаешь под словом все... На самом деле смысл критической секции прост, если кто-то вошёл, то все остальные при попытке входа - тормозят и ждут выхода.

По этому - что значит "одну на все"? В критическую секцию можно входить несколько раз, по этому создавать кажый раз новый объект нет необходимости. Чисто технически, можно использовать одну критическую секцию на всю программу, но это приведёт к лагам из-за возможного неоправдонного использования блокировок.

Критические секции рекомендуется создавать для переменной или группы переменных, с которыми идёт работа из нескольких нитей.

Допустим у нас есть переменные A, B, C и D. Мы работаем одновременно из нескольких нитей с A, B и C, D. При этом, пары A-B и C-D обрабатываются независимо друг от друга. В этом случае нам желательно создать две критические секции C1 и C2, которые будут защищать данные пар A-B и C-D соответсвенно.

Усложним ситуацию. Допустим мы хотим поработать одновременно со всеми четырьмя переменными. При этом, из соображения производительности, мы решили, что используем две критические секции. Это значит, что нам надо войти в обе.

Если таких мест в программе несколько, то вопрос порядка входа становится важным. Может возникнуть ситуация, назвваемая бесконечной блокировкой (дедлок, deadlock). Когда одна нить вошла в критическую секцию C2 и теперь пытается войти в C1, а другая вошла в C1 и теперь хочет войти в C2. Естественно, в этом случае программа останется блокированной навечно.

В этом случае решением является раз и навсегда определить порядок входа в критические секции. В более сложном виде это выглядит так: допустим у нас есть три критические секции A, B и C.

Если мы хотим работать только с данными, которые защищает A, B или С, то мы просто входим в соответсвующую критическую секцию и выходим по завершению.

Но если мы захотим использовать все данные, то мы должны входить в критические секции в выбранном порядке, здесь - по алфавиту:
A
B
C

Выход осуществляется в обратном порядке:

C
B
A

Если нам нужны данные только С и В, то мы входим только в порядке:

B
C

даже, если с B нам надо работать совсем немного и в самой глубине кода, работающего с C.

В общем случае, рекомендуется по возможности сокращать время, проводимое программой в критических секциях.

B)
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

Ну ты и выдал лекцию )))) Я знаю что такое критические секции ;) Вопрос о другом.

Код: Выделить всё

var
 cs1,cs2:TRTLCriticalSection;
...
 procedure P1;
 begin
  EnterCriticalSection(cs1);
  ..
  LeaveCriticalSection(cs1);
 end;
 
 procedure P2;
 begin
  EnterCriticalSection(cs2);
  ..
  LeaveCriticalSection(cs2);
 end;

begin
 InitCriticalSection(cs1);
 InitCriticalSection(cs2);
 ...
 DoneCriticalSection(cs1);
 DoneCriticalSection(cs2);
end.


вместо переменых cs1 и cs2 я могу использовать одну перменную ? Т.е.:

Код: Выделить всё

var
 cs:TRTLCriticalSection;
...
 procedure P1;
 begin
  EnterCriticalSection(cs);
  ..
  LeaveCriticalSection(cs);
 end;
 
 procedure P2;
 begin
  EnterCriticalSection(cs);
  ..
  LeaveCriticalSection(cs);
 end;

begin
 InitCriticalSection(cs);
 ...
 DoneCriticalSection(cs);
end.

Дело в том, что я совершенно не понимаю смысла перменной типа TRTLCriticalSection ...
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Переменная типа TRTLCriticalSection у программиста должна ассоциироваться с каким-нибудь ресурсом, над которым допустимо производить только атомарные (неделимые) операции. Сама переменная это своего рода псевдоним ресурса.

Например:
А:=Состояние счёта
А:=А+Вложение
Состояние счёта:=А

Это типичная атомарная операция. Если у вас в таблице хранится Состояние нескольких счетов, то можно для каждого сделать свою кр.секцию(1 вариант), или одну на всю таблицу(2 вариант). Если состояние счетов меняется часто, то более быстрым будет первый вариант, т.к. блокировки будут на уровне отдельных счетов, а не на уровне всей таблицы.
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

В СУБД обычно реализованы оба варианта и они "видят" друг друга, т.е, если идёт блокировка всей таблицы, то блокировка одной записи будет ждать и наоборот.

И важно! Выходить из критических секций следует в обратном вхождению порядке.
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

STAKANOV писал(а):Ну ты и выдал лекцию )))) Я знаю что такое критические секции  ;) Вопрос о другом.

Не могу ответить. Формально - можешь. А вот будет ли хуже... Надо знать как вызываются P1 и P2. Если P1 может параллельно работать одновременно только с P1, а P2 только с P2 - да. Если может быть P1 параллельно с P2 и они работают с разными данными, то не стоит.

Но опять же - где. На однопроцессорных компах разницы не будет. На SMP и многоядреных - будет.

STAKANOV писал(а):Дело в том, что я совершенно не понимаю смысла перменной типа TRTLCriticalSection ...

А я о чём писал? TRTLCriticalSection - хендл. Указатель на объект ядра. Никакой "внутренней структурой" с точки зрения паскаля не обладает.
Аватара пользователя
Иван Шихалев
энтузиаст
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург
Контактная информация:

Сообщение Иван Шихалев »

Народ, а не слабо :D по критическим секциям статью написать?
Гость_PVOzerski

Сообщение Гость_PVOzerski »

Но это все-таки не хэндл. В RTL эта штука описана ка record. Начинка зависит от платформы.
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

Гость_PVOzerski писал(а): Но это все-таки не хэндл. В RTL эта штука описана ка record. Начинка зависит от платформы.

Интересное кино, а что такое по твоему хендл? Или все остальные разработчики - састера мазохизма? :D В 90% случаев хендл - указатель на структуру ядра, используемую самим ядром, для обработки объекта. B)
PVOzerski
постоялец
Сообщения: 109
Зарегистрирован: 19.05.2005 13:45:10
Откуда: СПб
Контактная информация:

Сообщение PVOzerski »

Дык ведь указатель (или просто некий численный идентификатор), а не сама структура...
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

PVOzerski писал(а): Дык ведь указатель (или просто некий численный идентификатор), а не сама структура...

Дык, ты говоришь - "не хендл". Тогда я и спрашиваю - что по твоему имеет право считаться хендлом?
Гость_PVOzerski

Сообщение Гость_PVOzerski »

Идентификатор, но не структура - даже если она - массив или запись, содержащая идентификаторы. Может ведь быть и массив хэндлов, и запись или объект с полями-хэндлами. А иначе можно было бы и имя файла хэндлом назвать :)

Кстати, а можно ли назвать хэндлом указатель? ;) Особенно, если память виртуальная...
Ответить