Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

Был, сегодня, на собеседовании   Найти похожие ветки 

 
Verg ©   (2004-04-23 19:58) [80]


> она менее ресурсоемка.


Да? Есть основания так предпологать?
Я бы не осмелился....
Если она ведет учет того, какой поток именно ее захватил для обеспечния счетчика повторных вхождений, при этом таки заводит Event для ожидания освобождения, то уж всяко на "один квант" стоит дороже.
Не знаю точно про Windows, но опыт собственных "синхронизаторов" подсказывает, что критические секции обходятся несколько дороже, нежели элементарные "стоп - я сброшен".

Насчет try-finally - тут я полностью с тобой согласен :)) Просто за последние несколько дней на форумах у меня появилось ущущение, что эти блоки очень многие не любят, предпочитая goto и проч. :))))))))))


 
Sha ©   (2004-04-23 20:18) [81]

> Verg ©   (23.04.04 19:58) [80]
>> она менее ресурсоемка.
> Да? Есть основания так предпологать?

Ага, есть. Смотрел пару лет назад.


 
Игорь Шевченко ©   (2004-04-23 20:30) [82]

Verg ©   (23.04.04 19:58)

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


 
Игорь Шевченко ©   (2004-04-23 20:41) [83]

По поводу критических секций и Interlocked - я считаю, что операция проверки счетчика экземпляров, его изменение и выполнение каких-либо действий после проверки являет неделимой операцией, следовательно, защищать критической секцией надо операцию целиком. Мне кажется, что вариант с Intelocked-функциями может приводить к труднообнаруживаемым ошибками :)


 
Verg ©   (2004-04-23 21:03) [84]


>  Мне кажется, что вариант с Intelocked-функциями может приводить
> к труднообнаруживаемым ошибками :)


Зря кажется - это я тебе не "просто так" говорю :))))

В остальном...... - дело вкуса - как я уже говоил. Каждой задаче - свое решение....


 
Sha ©   (2004-04-23 22:02) [85]

> Verg ©   (23.04.04 21:03) [84]
> В остальном...... - дело вкуса - как я уже говоил. Каждой задаче - свое решение....

Подробнее.
Насколько помню, реализация критической секции для Intel сводится к следующему: это совокупность события, атомарного счетчика и данных, необходимых для отслеживания повторных входов(для нас это несущественно). При входе делаем InterlockedIncrement и анализируем результат: если можно пройти дальше, то проходим, если нет - встаем в ожидание. При выходе делаем InterlockedDecrement и анализируем результат: если в очереди кто-то есть, то его отпускаем.
При такой реализации почти никогда не будет работы с событием, что сказывается на производительности в лучшую сторону.
Можешь походить по коду под отладчиком а также сравнить время входа-выхода в критическую секцию со временем ожидания-сигнала отдельного события. Будешь приятно удивлен.
Так что не во вкусе дело :)


 
Игорь Шевченко ©   (2004-04-23 22:14) [86]

Verg ©   (23.04.04 21:03)

Не трудно будет привести замену критической секции InterLocked-фунциями в моем коде ? Или указать пост, где такая замена приведена.

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


 
Sha ©   (2004-04-23 23:26) [87]

> Игорь Шевченко ©   (23.04.04 22:14) [86]

Скока точно потоков обращаются к одиночке? Если больше одного, то его разорвут на части - никакой Interlocked не поможет. Надо иметь средство торможения всех, кроме одного.


 
nikkie ©   (2004-04-24 01:45) [88]

>[71] Sha
что-то я не могу понять глубинного смысла отсчета в обратную сторону, причем, начиная с единицы. почему было не сделать счетчик ссылок, как в TInterfacedObject или как было в THSSingleton?

тем более, я не понимаю смысла поправки [73] - зачем сначала Decrement, а потом два раза Increment? нельзя разве было написать просто
if InterLockedIncrement(Key)>0?

>Если больше одного, то его разорвут на части - никакой Interlocked не поможет.
безусловно. например, одновременный вызов FreeInstance в двух потоках может привести к утечке памяти - объект никогда не будет разрушен. только если понятно, что ни о какой потокозащищенности тут речи не идет, то зачем использовать Interlocked?


 
Verg ©   (2004-04-24 07:19) [89]


> Sha ©   (23.04.04 22:02) [85]


Нет, нет... подожди ка
> При входе делаем InterlockedIncrement и анализируем результат:
> если можно пройти дальше, то проходим, если нет - встаем
> в ожидание
. При выходе делаем InterlockedDecrement и анализируем
> результат: если в очереди кто-то есть, то его отпускаем.
>
> При такой реализации почти никогда не будет работы с событием,
> что сказывается на производительности в лучшую сторону.


Че-то я не понял: как же нет работы с событием, когда "встаем в ожидание". В ожидание-то как встаем? Чего и как ждем?


 
Verg ©   (2004-04-24 07:24) [90]


> Игорь Шевченко ©   (23.04.04 22:14) [86]



> Игорь Шевченко ©   (23.04.04 14:26) [38]
> unit HSSingleton;
>
> interface
>
> type
>  THSSingleton = class
>  private
>    FInstanceCount: Integer;
>  public
>    class function NewInstance: TObject; override;
>    procedure FreeInstance; override;
>  end;
>
> implementation
> uses
>  Windows;
>
> { THSSingleton }
>
> var
>  Instance: THSSingleton;
>  //CritSect: RTL_CRITICAL_SECTION;
>  key : integer = 0;
> procedure THSSingleton.FreeInstance;
> begin
>  while InterLockedExchange(key, 1) <>0 do sleep(1);//EnterCriticalSection(CritSect);
>  try
>    Dec(FInstanceCount);
>    if FInstanceCount = 0 then begin
>      inherited;
>      Instance := nil;
>    end;
>  finally
>    InterLockedExchange(Key, 0);//LeaveCriticalSection(CritSect);
>  end;
> end;
>
> class function THSSingleton.NewInstance: TObject;
> begin
>  Аналогично//EnterCriticalSection(CritSect);
>  try
>    if not Assigned(Instance) then
>      Instance := THSSingleton(inherited NewInstance);
>    Result := Instance;
>    Inc(Instance.FInstanceCount);
>  finally
>    Аналогично//LeaveCriticalSection(CritSect);
>  end;
> end;
>
>// initialization
>//  InitializeCriticalSection(CritSect);
>// finalization
>//  DeleteCriticalSection(CritSect);
> end.


 
Sha ©   (2004-04-24 09:14) [91]

Verg ©   (24.04.04 07:19) [89]
Ждем, конечно, события. Фишка в том, что ждем крайне редко, т.к. критическими секциями обычно защищают небольшие быстрые участки кода. Если же ждать приходится при каждом обращении, то и здесь мы ничего не теряем. Производительнеости будут равны. Но в этом случае стоит подумать - а на фига были нужны потоки: если мы все время ждем одного ресурса, то достаточно одного потока.


 
Sha ©   (2004-04-24 09:27) [92]

> nikkie ©   (24.04.04 01:45) [88]
> что-то я не могу понять глубинного смысла отсчета в обратную
> сторону, причем, начиная с единицы. почему было не сделать
> счетчик ссылок, как в TInterfacedObject или как было в THSSingleton?

Дело в том, что в возвращаемом результате InterlockedInc/Decrement гарантируется только знак. Считать можно и в прямую сторону, но только начиная с -2. Я выбрал первый из двух вариантов.

> тем более, я не понимаю смысла поправки [73] - зачем сначала
> Decrement, а потом два раза Increment? нельзя разве было
написать просто
if InterLockedIncrement(Key)>0?

Нет, по тем же причинам.

>> Если больше одного, то его разорвут на части - никакой Interlocked не поможет.
> безусловно. например, одновременный вызов FreeInstance в двух
> потоках может привести к утечке памяти - объект никогда не
> будет разрушен. только если понятно, что ни о какой
> потокозащищенности тут речи не идет, то зачем использовать Interlocked?

Ты прав, не обязательно. Можно обойтись Inc/Dec.
Просто, чуть выше han_malign ©   (23.04.04 16:39) [66] упомянул, что можно использовать Interlocked (конечно, имея ввиду однопотовый Singleton), в чем Игорь Шевченко ©   (23.04.04 17:04) [70] усомнился (имея ввиду многопотоковый вариант), и уже после этого я не поняв, что они не поняли друг друга, показал, как это могло бы выглядеть в случае с одним потоком :)


 
Sha ©   (2004-04-24 10:09) [93]

Verg ©   (24.04.04 07:24) [90]

Этот вариант проигрывает оригинальному по производительности.

P.S. На SLEEP"ах можно сделать синхронизацию потоков и без Interlocked (по крайней мере двух - это точно, для большего числа - не знаю, можно ли обобщить :)


 
Verg ©   (2004-04-24 10:59) [94]


> Sha ©   (24.04.04 10:09) [93]
> Verg ©   (24.04.04 07:24) [90]
>
> Этот вариант проигрывает оригинальному по производительности.


1. Оригинальный - это какой?
2. Поясни почему.


> P.S. На SLEEP"ах можно сделать синхронизацию потоков и без
> Interlocked (по крайней мере двух - это точно, для большего
> числа - не знаю, можно ли обобщить :)


Покажи как. Странно это - "для двух". Что же это за синхронизация такая?


 
Sha ©   (2004-04-24 12:26) [95]

> Verg ©   (24.04.04 10:59) [94]
> 1. Оригинальный - это какой?

Игорь Шевченко ©   (23.04.04 14:26) [38]

> 2. Поясни почему.

В случае прохода секции без ожидания они равноценны - оба используют Interlocked. А в случае занятости ресурса твой вариант ждет в среднем на 0.5 msec больше.  

> Покажи как. Странно это - "для двух". Что же это за синхронизация такая?

Это хорошая разминка для мозгов. Сначала попробуй сам. В известной реализации для двух процессов, кажется, требуется 4 флажка. Вроде можно сделать для произвольного заранее известного числа. Можно ли обобщить на N процессов - не знаю.


 
Verg ©   (2004-04-24 12:58) [96]


> Sha ©   (24.04.04 12:26) [95]


Неужели не понятно, что там вместо sleep-а можно было поставить и событие с автосбросом. Дело-то не в слипе. Синхронизация там вовсе не за счет него происходит. Если б там sleep(0) поставил, то что? Ты бы сказал, что в среднем на 0 ms?

Кроме того


> Фишка в том, что ждем крайне редко,


Так что, как же будет в среднем? ;))


> Это хорошая разминка для мозгов. Сначала попробуй сам.


Не вижу ни смысла, ни интереса в этой задаче.


 
Sha ©   (2004-04-24 13:33) [97]

> Verg ©   (24.04.04 12:58) [96]

> Неужели не понятно, что там вместо sleep-а можно было
> поставить и событие с автосбросом. Дело-то не в слипе.

Почему же не понятно, очень даже понятно. В этом случае ты бы сэмулировал работу критической секции и производительности сравнялись бы :). Это тебе должно быть понятно после Sha ©   (23.04.04 22:02) [85] :)

> Синхронизация там вовсе не за счет него происходит. Если б там
> sleep(0) поставил, то что? Ты бы сказал, что в среднем на 0 ms?

Не не угадал :) Я бы сказал, что ты впустую ешь время CPU для достижения того же результата, что и критическая секция :)

>> Фишка в том, что ждем крайне редко,
> Так что, как же будет в среднем? ;))

Я думаю, ты сам сможешь ответить на этот вопрос, используя информацию из Sha ©   (23.04.04 22:02) [85] :)

>> Это хорошая разминка для мозгов. Сначала попробуй сам.
> Не вижу ни смысла, ни интереса в этой задаче

Тогда не надо было спрашивать как?


 
Verg ©   (2004-04-24 14:12) [98]


> Я бы сказал, что ты впустую ешь время CPU для достижения
> того же результата, что и критическая секция :)


Нет. И ты об этом знаешь и я уже говорил об этом, что того же результата, что и критическая секция простым "семафором" не добиться.

Однако, когда рекурсивного вхождения не требуется и, т.о., нет необходимости постоянно (на каждую попытку входа) вести учет того, какой-же именно поток и сколько раз вошел в КС, то ответом на вопрос Игоря (о том как InterLocked...-том заменить КС) может служить мой ответ.

Не знаю, может у тебя есть другой ответ, но ты его не показал, предложив "размять мозги" почему-то мне.


> Тогда не надо было спрашивать как?


Ах извини, конечно, бес попутал. Больше ничего не спрошу.


 
Sha ©   (2004-04-24 14:31) [99]

> Verg ©   (24.04.04 14:12) [98]
> Однако, когда рекурсивного вхождения не требуется...,
> то ответом на вопрос Игоря (о том как InterLocked...-том
> заменить КС) может служить мой ответ.

Не возражаю, но крит. секция быстрее. Только это и было сказано.

> Не знаю, может у тебя есть другой ответ, но ты его не показал,
> предложив "размять мозги" почему-то мне.

Другого ответа в общем случае я не знаю.
По-моему, для реализации многопоточного класса TSingleton лучше всего подходит именно критическая секция.


 
nikkie ©   (2004-04-24 15:11) [100]

Дело в том, что в возвращаемом результате InterlockedInc/Decrement гарантируется только знак.
в общем-то, да. на win95 и winNT3.51. на win98, winNT4.0 и выше гарантируется возврат правильного результирующего значения.

Считать можно и в прямую сторону, но только начиная с -2. Я выбрал первый из двух вариантов.
как это? получается реализация TInterfacedObject содержит грубейшую ошибку?


 
Sha ©   (2004-04-24 15:46) [101]

> nikkie ©   (24.04.04 15:11) [100]
> как это? получается реализация TInterfacedObject содержит грубейшую ошибку?

Почему ты так решил?


 
Sha ©   (2004-04-24 16:02) [102]

If the result of the increment is zero, the return value is zero.
If the result of the increment is less than zero, the return value is less than zero. If the result of the increment is greater than zero, the return value is greater than zero. A nonzero return value may not be equal to the result of the increment.

Можно использовать любой из переходов -N/0 или 0/+N.
Я обычно использую первый, TInterfacedObject - второй.
Всего получается 2х2=4 вариантов использования InterlockedIncrement/InterlockedDecrement.


 
Игорь Шевченко ©   (2004-04-24 18:11) [103]

А все-таки с критической секцией код читается легче, на мой взгляд :))

С уважением ко всем участникам,


 
default ©   (2004-04-24 21:00) [104]

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


 
nikkie ©   (2004-04-24 21:54) [105]

>Sha
>Почему ты так решил?
потому, что ты сказал "Считать можно и в прямую сторону, но только начиная с -2", а TIntrefacedObject считает от 0. либо я чего-то не понимаю.

>Игорь Шевченко
>А все-таки с критической секцией код читается легче, на мой взгляд :))
дело не только в легкости чтения. просто код, использующий Interlocked..., в данном случае не является потокобезопасным - надо ведь еще синхронизировать доступ к Instance одновременно с изменением FInstanceCount. так что критическая секция необходима (если не стукнет воспользоваться для синхронизации объектами ядра, что здесь не к месту, конечно).


 
Юрий Зотов ©   (2004-04-24 22:06) [106]

> default ©   (24.04.04 21:00) [104]

Вообще-то, на работу обычно берут работать, а не учиться. Понятно, что на новом месте что-то осваивать все равно придется, но это смотря что осваивать. Если конкретный проект - это нормально, а вот если программирование - слишком дорогой работник получится.


 
Sha ©   (2004-04-24 22:12) [107]

> nikkie ©   (24.04.04 21:54) [105]
>> Почему ты так решил?
> потому, что ты сказал "Считать можно и в прямую сторону, но
> только начиная с -2"

Да согласен. Надо было выразиться точнее: "Используя переход -1/0 можно считать и в прямую сторону, но только начиная с -2".
Вообще в нашем случае можно было бы:
- используя переход -1/0 cчитать в прямую сторону, начиная с -2,
- используя переход 0/1 cчитать в прямую сторону, начиная с -1,
- используя переход -1/0 cчитать в обратную сторону, начиная с 1,
- используя переход 0/1 cчитать в обратную сторону, начиная с 2.

> а TIntrefacedObject считает от 0. либо я чего-то не понимаю.

У IntrefacedObject особый случай, где надо предпринять какие-либо действия - начало счета, т.е. шаг0. У нас же - шаг1, в этом-то все дело. Поэтому он свободно использует для освобождения переход из состояния 1 в состояние 0.

Перечитал свои посты в этой ветке - ужас, сколько неточностей. Кстати, ты был прав - та поправка не требовалась. Я перестраховался напрасно.


 
Sha ©   (2004-04-24 22:27) [108]

В смысле можно было написать:
procedure THSSingleton.FreeInstance;
begin;
if InterLockedIncrement(Key)>0
then begin;
  inherited;
  Instance:=nil;
  end;
end;



Страницы: 1 2 3 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.67 MB
Время: 0.046 c
1-1083148179
jek_
2004-04-28 14:29
2004.05.16
Дата модификации файла


3-1082533864
mich
2004-04-21 11:51
2004.05.16
Метод Synchronize


9-1072825408
Jenaxx
2003-12-31 02:03
2004.05.16
КТо нить может помочь переделать прогу,


3-1082439362
Wild_arg
2004-04-20 09:36
2004.05.16
try...except...end в T-SQL


1-1083047567
basken
2004-04-27 10:32
2004.05.16
Как принудительно показать хинт контрола?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский