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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.004 c
1-1267095254
EgorovAlex
2010-02-25 13:54
2011.09.25
Редирект сообщения MouseWheel


2-1307213708
Gu
2011-06-04 22:55
2011.09.25
Определить наличие звуковухи


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


6-1241804128
DVM
2009-05-08 21:35
2011.09.25
Определить режим работы сокета: блок. или неблок. в Winsock


15-1306822456
Evgeniy_gd
2011-05-31 10:14
2011.09.25
Покритикуйте инструкцию по использованию флешек USB.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский