Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.09.25;
Скачать: CL | DM;

Вниз

Совет по использованию критических секций.   Найти похожие ветки 

 
Alex_C   (2011-06-04 16:21) [0]

Есть очень большая и глобальная программа. В этой программе есть много (эдак около 10) отдельных тредов пполучения данных из инета, телнета, данных с оборудования. Естественно получение и обработку полученных данных нужно согласовать.
Я не являюсь проф. программистом, и все данные я читаю в книжках и в инете. Большое спасибо СереюМ - здешнему пользователю , который эпизодически наставляет меня на путь истинный :)
Теперь к делу: согласование получения и обработки данных я использую критические секции.
Вотпросы на которые я не смог найти ответов в литературе:
1. Для каждого независимого потока нормально что я использую отдельную критическую секцию, если с другими потоками он не завязан?
2. Можно ли в основном потоке использовать критические секции? Или только метод Synchronize из потоков?
3. Мне в потоке нужно подождать некоторого действия. Application.ProcessMessage использовать нельзя. Что лучше?


 
_Юрий   (2011-06-04 16:29) [1]


> 1. Для каждого независимого потока нормально что я использую
> отдельную критическую секцию, если с другими потоками он
> не завязан?


Если поток "не завязан с другими", крит секции не нужны.


> 2. Можно ли в основном потоке использовать критические секции?
>  Или только метод Synchronize из потоков?

Критические секции всегда используются разными потоками.  Если секцию использует только один поток, в ней нет никакого смысла. Является ли поток главным или нет - с т. зр. крит секции неважно.


> 3. Мне в потоке нужно подождать некоторого действия. Application.
> ProcessMessage использовать нельзя. Что лучше?


WaitForSingleObject
или же организовать очередь сообщений, и ждать сообщеня  в стандартном цикле обработки
while GetMessage(...) ...


 
Ega23 ©   (2011-06-04 16:33) [2]

Крит.секция нужна для защиты целостности. Допустим, один поток читает массив, а второй его в этот момент изменяет. Нехорошо.
Если только чтение - то можно и без крит.секций. Если с изменением, то тогда нужно.
И ещё момент: крит.секция не принадлежит контексту какого-либо потока, она отдельно, сама по себе существует.


 
Alex_C   (2011-06-04 16:45) [3]

Спасибо большое ребята за ответы!
Тепрь продолжение: я несколько слукавил, что разместил сообщение для начинающих - тут просто самое доброжелательное отношение.
Теперь более конкретно:

> Если поток "не завязан с другими", крит секции не нужны.


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

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


Вот тут пожайлуста по подробнее. Сколько читал литературы - так и не смог получить ответа на такой вопрос: есть основной поток, есть много (не один) тредов. Все это надо согласовать. Понятно, что для занесения данных в одну БД - нужна одна и таже КС - тут без вопросов. А если 2 БД - с отдельными потоками для каждой... Можно ли использовать разные КС? Использую разные КС - затык получается в них. Пока не пойму вот эту идеологию!


> И ещё момент: крит.секция не принадлежит контексту какого-
> либо потока, она отдельно, сама по себе существует.


Вот знаю это...  Читал.
Вот для тупого: можно вот тут ОЧЕНЬ подробно: вот ведь именно в этом у меня в проге проблема - но так до конца эту проблему и не понял! Буду очень благодарен если приведете отрывки кода ну или так на словах!


 
Alex_C   (2011-06-04 16:48) [4]

Да вот еще!
Теперь мысть которую сказал Ega23:
как надо объявлять КС: как отдельную переменную в классе (не в потоке, а имеенно в классе!) или как глобальную?


 
Юрий Зотов ©   (2011-06-04 17:05) [5]

> Alex_C   (04.06.11 16:21)

1. Для каждого независимого потока нормально что я использую отдельную критическую секцию, если с другими потоками он не завязан?

Критические секции (как и другие объекты синхронизации) используются для синхронизации потоков - когда один поток должен подождать окончания какой-то операции, выполняемой другим потоком. Если же поток никак не связан с другими потоками, то зачем его с чем-то там сихронизировать? Незачем.

2. Можно ли в основном потоке использовать критические секции? Или только метод Synchronize из потоков?

Тут либо у Вас некое смешение понятий, либо я не так Вас понял. В основном потоке использовать критические секции можно (если нужно), но метод Synchronize - это немного из другой оперы. Его суть в том, что, хотя он и принадлежит объекту TThread, выполняется он все равно в главном потоке. Естественно, пока он выполняется, главный поток ничего другого делать не будет - никакой поток не может делать два дела одновременно.

3. Мне в потоке нужно подождать некоторого действия.
Application.ProcessMessage использовать нельзя.


Тут снова или смешение понятий, или я не так Вас понял. Метод Application.ProcessMessages НЕ позволяет подождать некоторого действия. Он всего лишь обрабатывает сообщения Windows, накопившиеся в очереди главного потока - но при этом он ничего не ждет. Обычно Application.ProcessMessages используется для того, чтобы у юзера не создавалось впечатление "зависания" программы.

Если же нужно подождать окончания какого-то действия, то нужно либо использовать объекты синхронизации, либо функции WaiForXXXObject. Что лучше - это зависит от того, чего конкретно нам надо дождаться.


 
Alex_C   (2011-06-04 17:34) [6]


> Критические секции (как и другие объекты синхронизации)
> используются для синхронизации потоков


Вот-вот! Подошли к самому главному!
Можно ли их использовать для сихронизазии с ОСНОВНЫМ потоком тредов? Ну я думаю понятно сказал? Если что - я попытаюсь пояснит кодом. Но мне именно интересен ен код, а идеология!

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


Вы меня не поняли. То, что метод Synchronize выполняется в основном потоке - я знаю.
У меня

> смешение понятий

вот в чем:
есть основной поток, получающий данные от пользователя. Приходят данные от треда - их нужно согласовать с данными полученными от пользователя. Вот для этого можно использовать критические секции?
Ну вот чтоб было понятно: в треде получаю данные из инета - это долго, они сами по себе получаются. Теперь я их должен внести в общую БД, а в это время и пользователь в БД вносит свои данные. Это надо как то разграничить. Можно ли при этом использовать КС?

> Если же нужно подождать окончания какого-то действия, то
> нужно либо использовать объекты синхронизации, либо функции
> WaiForXXXObject.


Сейчас дома... Тут тоже не все так однозначно. Чтоб пояснить тут приведу чуть позднее код. Думаю тут все понятнее станет.


 
Юрий Зотов ©   (2011-06-04 17:45) [7]


> в треде получаю данные из инета это долго, они сами по себе
> получаются. Теперь я их должен внести в общую БД, а в это время и
> пользователь в БД вносит свои данные. Это надо как то разграничить.
> Можно ли при этом использовать КС?

Почему нет? Можно. Главный поток и дополнительный поток будут использовать общий код для внесения данных в БД. Этот код надо окружить критической секцией и сделать его максимально быстрым, чтобы потоки ждали друг друга как можно меньше. И еще надо предусмотреть, чтобы в других местах программы эти два потока друг друга нигде не ожидали, иначе может возникнуть взаимная блокировка (deadlock) - каждый поток ждет другого, а в результате все встало намертво.


 
Юрий Зотов ©   (2011-06-04 18:00) [8]

> Теперь я их должен внести в общую БД, а в это время и
> пользователь в БД вносит свои данные. Это надо как то разграничить

А вот тут нужно хорошо подумать - действительно ли надо это разграничивать? Ведь сервер БД тоже не дурак, он сам может многое разрулить.

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


 
Anatoly Podgoretsky ©   (2011-06-04 18:48) [9]

> Юрий Зотов  (04.06.2011 18:00:08)  [8]

Потоки, один поток, куча компьютеров - это нигогда синхронизировать не надо,
сервер сам все разрулит, а если возникло такое желание, то надо
перепроектировать задачу.


 
Alex_C   (2011-06-04 18:49) [10]


> Главный поток и дополнительный поток будут использовать
> общий код для внесения данных в БД. Этот код надо окружить
> критической секцией и сделать его максимально быстрым, чтобы
> потоки ждали друг друга как можно меньше. И еще надо предусмотреть,
>  чтобы в других местах программы эти два потока друг друга
> нигде не ожидали, иначе может возникнуть взаимная блокировка
> (deadlock) - каждый поток ждет другого, а в результате все
> встало намертво.


Да, да совершенно верно! Про это я тоже знаю! То нам - доли секунд обработки - таких коллиззий не должно возникать!
Но Вы абсолютно правы - коллизии то есть - т.е. возникают они из за этого!
Я уже весь код (месяц этим занимался) ограничил КС. Да, сейчас зависов стало мало - ну часов через 20 работы программы. Но они есть. Значит надо искать далее!


 
Alex_C   (2011-06-04 18:51) [11]


> сервер сам все разрулит


Нет сервера. Есть ОДИН компьютер. Задача достаточно общая. Я не хочу тут писать, но в личку могу написать задачу.


 
Anatoly Podgoretsky ©   (2011-06-04 19:00) [12]

> Alex_C  (04.06.2011 18:51:11)  [11]

Мы не про твой компьютер говорили, а про базы


 
Loginov Dmitry ©   (2011-06-04 19:02) [13]


> Ну вот чтоб было понятно: в треде получаю данные из инета
> - это долго, они сами по себе получаются. Теперь я их должен
> внести в общую БД, а в это время и пользователь в БД вносит
> свои данные. Это надо как то разграничить. Можно ли при
> этом использовать КС?


Какую СУБД используете и какие компоненты доступа к данным?
Следует учитывать, что для работы стандартных DB-компонетов, поставляемых с Delphi, каждый поток для обращения к БД должен устанавливать отдельное подключение к БД.
Имхо, критические секции в данном случае мало чем могут помочь.


 
Loginov Dmitry ©   (2011-06-04 19:04) [14]


> я несколько слукавил, что разместил сообщение
> для начинающих - тут просто самое доброжелательное отношение.
>  


А нужно было в какую?


 
Anatoly Podgoretsky ©   (2011-06-04 19:46) [15]

> Loginov Dmitry  (04.06.2011 19:04:14)  [14]

Да правильно он разместил.


 
Alex_C   (2011-06-05 14:55) [16]

Большое спасибо за ответы. Вот что я бы хотел уточнить:
Есть массив. Есть ф-ция получающая из этого массива какие то данные. Из разных тредов к этой ф-ции общащаются потоки. Переменные, которые используются для получения данных из массива - локальные для данной ф-ции. Т.к. тут происходит только чтение из массива, критические секции тут не нужны.  Правильно?


 
sniknik ©   (2011-06-05 15:04) [17]

> критические секции тут не нужны.
если данные не меняются в процессе (неважно где) и начальное заполнение происходит гарантированно до любого обращения/чтения, и массив это именно массив, а не VCL список любого типа, то да правильно.

но лучше бы вместо описаний привел код. там было бы видней правильно или нет.


 
Alex_C   (2011-06-05 16:22) [18]


> но лучше бы вместо описаний привел код. там было бы видней
> правильно или нет.



 TMode = record
   ModeName: string;
   ModeType: string;
   ModeADIF: string;
 end;

var
 Modes: array of TMode;

function GetDXCCModeFromMode(Mode: string): string;
var
 i: integer;
begin
 Result := Mode;
 EnterCriticalSection(EditModeTableCS);
 try
   for i := 0 to Length(Modes) - 1 do
   begin
     if Modes[i].ModeName = Mode then
     begin
       Result := UpperCase(Modes[i].ModeType);
       Break;
     end;
   end;
 finally
   LeaveCriticalSection(EditModeTableCS);
 end;
end;




> если данные не меняются в процессе (неважно где) и начальное
> заполнение происходит гарантированно до любого обращения/чтения,
>  и массив это именно массив


Да, код выше.


 
sniknik ©   (2011-06-05 16:44) [19]

код должен показывать логику которую ранее описывал словами, а не жалкий ничего не значащий огрызок.
тут например нет заполнения массива, значит он нулевой, и значит  показанный кусок  ВООБЩЕ не нужен (просто вместо присвоения функции присвоить передаваемый внутрь Mode и все), чего уж на критических секциях останавливаться.


 
Alex_C   (2011-06-06 15:31) [20]


> тут например нет заполнения массива

Массив заполняется в начале работы программы или же в определенные моменты, когда общащение к нему невозможно.
В данном случае я задал вопрос конкретно об этом куске кода.


 
sniknik ©   (2011-06-06 21:27) [21]

> В данном случае я задал вопрос конкретно об этом куске кода.
в данном куске нет взаимодействия, это так сказать вообще "моно" кусок, а взаимодействие только в "стерео"/"квадро"/... (больше 1).

т.что "кусочного" ответа просто нет.


 
sniknik ©   (2011-06-06 21:32) [22]

> когда общащение к нему невозможно.
вот как решается, что "общащение невозможно"? если без критических секций/синхронизаций и при работающих потоках в которых чтение.



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

Текущий архив: 2011.09.25;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.011 c
15-1306179935
DmitriyG.
2011-05-23 23:45
2011.09.25
Возврат интерфейса в Builder


1-1265708544
LightGreen
2010-02-09 12:42
2011.09.25
Вызов inherited определённого базового класса


1-1267095254
EgorovAlex
2010-02-25 13:54
2011.09.25
Редирект сообщения MouseWheel


2-1307346032
harisma
2011-06-06 11:40
2011.09.25
Цикл по элементам TInterfaceList


2-1307190079
Alex_C
2011-06-04 16:21
2011.09.25
Совет по использованию критических секций.