Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование CriticalSection 
:(
    Опции темы
bns12
Дата 10.9.2008, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 7.5.2008

Репутация: нет
Всего: нет



Подскажите, пожалуйста, правильно ли я делаю:

1) я вставляю EnterCryticalSection первым оператором критической процедуры, к которой обращаюсь из нескольких потоков. Может быть, EnterCryticalSection нужно ставить перед командой потока, вызывающей эту процедуру?

2) я вставляю EnterCryticalSection первым оператором критической процедуры, к которой обращаюсь из нескольких потоков. При этом в процедуру передается параметр. При одновременном обращении к процедуре нескольких потоков параметры будут конфликтовать (затирать друг друга)?

3) я вставляю EnterCryticalSection первым оператором критической процедуры, к которой обращаюсь из нескольких потоков.  Чтобы избежать зависания использую TryEnterCriticalSection:
Код

procedure CriticalProcedure( const Param : integer );
var Cnt : integer;
begin
          Cnt := 0;
          while not TryEnterCriticalSection( CS ) do begin
             if Cnt = 10 then begin
                Exit;
             end;
             Sleep( 500 );
             Inc( Cnt );
          end;
          ...
          LeaveCriticalSEction( CS );
end;


Переменная Cnt будет общая для всех потоков или каждый поток работет со своей копией Cnt?

Спасибо.
PM MAIL   Вверх
bems
Дата 10.9.2008, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(bns12 @  10.9.2008,  17:16 Найти цитируемый пост)
Переменная Cnt будет общая для всех потоков или каждый поток работет со своей копией Cnt?
она лежит в стеке, а у каждого потока свой стек, поэтому тут все нормльно


Цитата(bns12 @  10.9.2008,  17:16 Найти цитируемый пост)
При одновременном обращении к процедуре нескольких потоков параметры будут конфликтовать (затирать друг друга)?
для типов не являющихся скрытыми указателями - все нормально, для являющихся - нормально при условии, что IsMultiThread=true


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Felan
Дата 11.9.2008, 06:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: 2
Всего: 7



Цитата(bns12 @  10.9.2008,  19:16 Найти цитируемый пост)
3) я вставляю EnterCryticalSection первым оператором критической процедуры, к которой обращаюсь из нескольких потоков.  Чтобы избежать зависания использую TryEnterCriticalSection:

Зависания чего ты пытаешь избежать?
Если зависания потока, то это бессмысленно, т.к. если он будет ожидать, то не будут расходоваться ресурсы, а так он хоть и не сильно много, но все-таки их отжирает.

Если это у тебя VCL поток, и ты пытаешься избежать зависания пользовательского интерфейса, то в цикле надо сделать Application.ProcessMessage.

Цитата(bns12 @  10.9.2008,  19:16 Найти цитируемый пост)
Переменная Cnt будет общая для всех потоков или каждый поток работет со своей копией Cnt?

Со своей копией. Она тоже в стеке потока.

ЗЫЖ Вообще для входы/выходы из критических секций лучше всего в Try-Finally брать. ТАк... на всякий  случай.


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
Felan
Дата 11.9.2008, 07:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: 2
Всего: 7



Цитата(bems @  10.9.2008,  21:59 Найти цитируемый пост)
для типов не являющихся скрытыми указателями - все нормально, для являющихся - нормально при условии, что IsMultiThread=true 

Нет.
Эта переменная для менеджера памяти Delphi. К синхронизации она не имеет отношения.


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
bems
Дата 11.9.2008, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(Felan @  11.9.2008,  07:00 Найти цитируемый пост)
Эта переменная для менеджера памяти Delphi. К синхронизации она не имеет отношения.
как это не имеет? по твоему увеличить счетчик ссылок на строку (например при передаче ее в процедуру) можно одинаково в многопоточном и однопоточном приложениях?



--------------------
Обижено школьников: 8
PM MAIL   Вверх
bems
Дата 11.9.2008, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Прошу прощения, как оказалось счетчик ссылок строки всегда обрабатывается атомарно, даже если есть всего один поток.
Но при передаче интерфейса в процедуру (а точнее при выходе из нее) все равно нужен IsMultiThread

Код

procedure proc(a:IUnknown);
begin
//EnterCriticalSection
a:=TInterfacedObject.Create;
AllocConsole;
Writeln(dword(a));
//LeaveCriticalSection
end;//тут освобождение объекта, включающее FreeMem

procedure TForm1.Button1Click(Sender: TObject);
var o:TInterfacedObject;
begin     //IsMultiThread:=True;
o:=nil;
proc(o);
end;



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Felan
Дата 12.9.2008, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: 2
Всего: 7



Цитата(bems @  11.9.2008,  21:49 Найти цитируемый пост)
Но при передаче интерфейса в процедуру (а точнее при выходе из нее) все равно нужен IsMultiThread

Ну, во-первых, ниче не понял. По подробнее можно?

А во вторых, все, что ты говоришь, относится к менеджеру памяти и, вероятно, механизмам подсчета ссылок специфичным для делфи. А к синхронизации доступа к данным это отношения не имеет. Т.е. если два потока обращаются к одному ресурсу, неважно к какому, хоть десять раз IsMultiThread устанавливай, все равно нужна синхронизация.


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
bems
Дата 12.9.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(Felan @  12.9.2008,  07:44 Найти цитируемый пост)
все, что ты говоришь, относится к менеджеру памяти и, вероятно, механизмам подсчета ссылок специфичным для делфи. А к синхронизации доступа к данным это отношения не имеет
то что я говорю относиться к внутренним структурам данных менеджера памяти, доступ к которым осуществляется с использованием критической секции, которой влядеет менеджер памяти. 

Топикстартер спрашивал нормально ли будет сделать так:
Цитата(bns12 @  10.9.2008,  17:16 Найти цитируемый пост)
procedure CriticalProcedure( const Param : integer );
var Cnt : integer;
begin
          Cnt := 0;
          while not TryEnterCriticalSection( CS ) do begin
             if Cnt = 10 then begin
                Exit;
             end;
             Sleep( 500 );
             Inc( Cnt );
          end;
          ...
          LeaveCriticalSEction( CS );
end;

В этом коде действия, подставляемые компилятором после начала процедуры но до первой строки пользовательского кода (и после последней строки но до возврата из процедуры) выполняются вне критической секции пользователя. Значит нужно включить использование критической секции менеджера памяти с помощью IsMultiThread

Цитата(Felan @  12.9.2008,  07:44 Найти цитируемый пост)
Т.е. если два потока обращаются к одному ресурсу, неважно к какому, хоть десять раз IsMultiThread устанавливай, все равно нужна синхронизация. 
это верно. а обратное утверждение - не всегда, т.е. если весь код тела процедуры/функции синхронизирован, то это не значит что синхронизирован весь код процедуры

Цитата(Felan @  12.9.2008,  07:44 Найти цитируемый пост)
ниче не понял. По подробнее можно?
задай вопрос конкретнее



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Felan
Дата 13.9.2008, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: 2
Всего: 7



Цитата(bems @  12.9.2008,  19:13 Найти цитируемый пост)
то что я говорю относиться к внутренним структурам данных менеджера памяти, доступ к которым осуществляется с использованием критической секции, которой влядеет менеджер памяти. 

Ну и я о том же smile

Цитата(bems @  12.9.2008,  19:13 Найти цитируемый пост)
В этом коде действия, подставляемые компилятором после начала процедуры но до первой строки пользовательского кода (и после последней строки но до возврата из процедуры) выполняются вне критической секции пользователя. Значит нужно включить использование критической секции менеджера памяти с помощью IsMultiThread

Полностью согласен.

Цитата(bems @  12.9.2008,  19:13 Найти цитируемый пост)
это верно. а обратное утверждение - не всегда, т.е. если весь код тела процедуры/функции синхронизирован, то это не значит что синхронизирован весь код процедуры

Не понял, как звучит обратное утверждение?

Мне кажется, что мы об одном и том же... Я лично не сталкивался с флагом IsMultiThread, только читал про него. Многопоточные приложения писал и пишу, но пользую TThread, поэтому не думаю об этом флаге.

На вопрос топикастера ты ответил:

Цитата(bems @  10.9.2008,  21:59 Найти цитируемый пост)
для типов не являющихся скрытыми указателями - все нормально, для являющихся - нормально при условии, что IsMultiThread=true

Я утверждаю, что установки этого флага не достаточно. Т.к. этот флаг будет отвечать за выделение памяти под данные из разных потоков, но не за доступ к ним. Доступ к ним надо синхронизировать отдельно.
А в случае топикастера вообще все параллельно. У него данные только в стеке, так что для каждого потока свои будут smile Вот если у него вместо "..." есть код, который работает с "общими" для потоков ресурсами, то тогда в любом случае ему надо делать синхронизацию в ручную.


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0538 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.