Форум: "Начинающим";
Текущий архив: 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