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

Вниз

Потоки. Нужна ли синхронизация?   Найти похожие ветки 

 
vint45   (2008-06-17 12:42) [0]

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


 
Поросенок Винни-Пух ©   (2008-06-17 12:43) [1]

а нафик их периодически читать, если их значения никто не меняет?


 
vint45   (2008-06-17 12:47) [2]

меняют сами потоки (за исключением главного), производя некоторую деятельность


 
Palladin ©   (2008-06-17 12:51) [3]


> когда потоки пытаются изменять, а не читать общие переменные

тема главного потока не раскрыта, он менять то их (общие переменные) будет время от времени или они один раз назначные и форева во веки веков?


 
MsGuns ©   (2008-06-17 12:51) [4]

В данном случае надо в теле модуля, доступного всем юнитам-потокам, зарезервировать список с адресами объектов-кэшей для каждого потока.
Каждый поток при запуске добавляет в этот список указатель на собственный объект-кэш (в простейшем случае record) и в процессе выполнения пишет в него свои значения, не "мешая" другим. Гл.форма (или что там выполняется в основном потоке) с определенной периодичностью (TTimer) анализирует содержимое кэшей и отображает их в чем-то визуальном.
Потоки пишут в кэши через Synchronize (хотя, возможно, это и не обязательно)


 
Поросенок Винни-Пух ©   (2008-06-17 12:52) [5]

меняют сами потоки (за исключением главного), производя некоторую деятельность

И что?
Передай им все значения при создании потоков.
И не читай то что не меняется.


 
Palladin ©   (2008-06-17 12:55) [6]

фу блин... задачу воспринял с точностью до наоборот...

решение зависит от частоты изменения этих локальных переменных и от того насколько часто необходимо считывать статданные...


 
vint45   (2008-06-17 13:02) [7]


> Palladin ©

задачей главного потока является отображение в форме значений локальных переменных изменяемых в остальных потоках


> MsGuns ©
Потоки пишут в кэши через Synchronize (хотя, возможно, это и не обязательно)

вот меня как раз этот вопрос и интересует


 
vint45   (2008-06-17 13:14) [8]


> Palladin ©   (17.06.08 12:55) [6]
> фу блин... задачу воспринял с точностью до наоборот...
>
> решение зависит от частоты изменения этих локальных переменных
> и от того насколько часто необходимо считывать статданные.
> ..

я вас не совсем понял.. т.е. если переменные изменяются редко, то синхронизацию можно не проводить?


 
Leonid Troyanovsky ©   (2008-06-17 13:16) [9]


> vint45   (17.06.08 12:42)  

> Вопрос. Надо ли помещать в критическую секцию процесс чтения
> локальных переменных главным потоком из остальных потоков?

Любое обращение к перменной из любого потока должно идти через КС.
Либо через InterLocked*. Либо из вторичных потоков через Synchronize.

--
Regards, LVT.


 
Поросенок Винни-Пух ©   (2008-06-17 13:17) [10]

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

Посылать сообщение в главный поток со значениями когда эти значения меняются.
В главном ничего не читать


 
vint45   (2008-06-17 13:18) [11]


> Leonid Troyanovsky ©   (17.06.08 13:16) [9]

Спасибо


 
Leonid Troyanovsky ©   (2008-06-17 13:18) [12]


> MsGuns ©   (17.06.08 12:51) [4]

> Потоки пишут в кэши через Synchronize (хотя, возможно, это
> и не обязательно)

С чего бы это "возможно"?

--
Regards, LVT.


 
Palladin ©   (2008-06-17 13:57) [13]


> я вас не совсем понял.. т.е. если переменные изменяются
> редко, то синхронизацию можно не проводить?

нет, от этого зависит путь решения

1. если переменные изменяются редко, то имеет смысл просто организовать из потоков SendMessage в главный поток с уведомлением об изменении той или иной переменной в данном потоке
2. если переменные меняются умопомрачительно быстро, то так же два выбора, но оба с применением критических секций
2.а либо реализовать на основе таймеров забор значений, но он мне не нравится
2.б либо реализовать доп.поток, сборщик данных, аналог таймера, который с определенным интервалом будет синхронизировать собранные данные с главным потоком приложения


 
MsGuns ©   (2008-06-17 15:57) [14]

>Leonid Troyanovsky ©   (17.06.08 13:18) [12]
>> Потоки пишут в кэши через Synchronize (хотя, возможно, это
>> и не обязательно)
>С чего бы это "возможно"?

Если при опросе гл.потоком не слишком важен факт, "успел" ли поток записать все, что "хотел". Например, при прорисовке статусов потоков через интервалы (т.е. что-то можно "дорисовать" при следующем "опросе"). Т.к. поток не влияет на канву, его действия в общем случае можно не синхронизировать, ибо он пишет только в "свои" участки памяти, не пересекающиеся ни с кэшами других потоков, ни с памятью гл.потока, занятой "своими" данными


 
Тын-Дын ©   (2008-06-17 17:48) [15]


> Palladin ©   (17.06.08 13:57) [13]
>
> > я вас не совсем понял.. т.е. если переменные изменяются
>
> > редко, то синхронизацию можно не проводить?
>
> нет, от этого зависит путь решения
>
> 1. если переменные изменяются редко, то имеет смысл просто
> организовать из потоков SendMessage в главный поток с уведомлением
> об изменении той или иной переменной в данном потоке


Это подход не с той стороны.
Инициатор - основной поток, а не дополнительные. По условию.


> 2.а либо реализовать на основе таймеров забор значений,
> но он мне не нравится


Нет такого подхода при работе с потокми.


> 2.б либо реализовать доп.поток, сборщик данных, аналог таймера,
>  который с определенным интервалом будет синхронизировать
> собранные данные с главным потоком приложения


См. пред. пункт.

Резюме - только критичские секции (либо Synchronize).


 
Leonid Troyanovsky ©   (2008-06-17 18:08) [16]


> MsGuns ©   (17.06.08 15:57) [14]

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

Не только ж канва нуждается в синхронизации.
А насчет пересечений в вопросе прямо cказано

> считывать из главного потока значения некоторых локальных переменных
> этих потоков

Отсутствие синхронизации доступа здесь вовсе недопустимо,
бо считанное будет, в общем случае, абсурдом.

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

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2008-06-17 18:18) [17]


> Тын-Дын ©   (17.06.08 17:48) [15]

> > организовать из потоков SendMessage в главный поток с
> уведомлением
> > об изменении той или иной переменной в данном потоке

> Инициатор - основной поток, а не дополнительные. По условию.

Если все изменения становятся доступны первичному потоку,
то какая нах разница - он волен в проявлении своей инициативы,
работая со своей копией данных.

Синхронизацию через SendMessage окну первичного потока пользовали
раннии версии дельфи, и особого криминала здесь замечено не было, за исключением некоторых вырожденных случаев.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2008-06-17 18:24) [18]


> Тын-Дын ©   (17.06.08 17:48) [15]

> Резюме - только критичские секции (либо Synchronize).

Synchronize работает с той же стороны, что и SendMessage.
Впрочем, это не препятствие, см. также [16].

Главное, чтобы синхронизация имела место, что, собс-но,
и беспокоило вопрошающего, IMHO.

--
Regards, LVT.


 
Palladin ©   (2008-06-17 18:44) [19]


> Это подход не с той стороны.
> Инициатор - основной поток, а не дополнительные. По условию.

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


 
Palladin ©   (2008-06-17 18:50) [20]


> Нет такого подхода при работе с потокми.

да ты что... обоснуй


 
Тын-Дын ©   (2008-06-17 19:11) [21]

Да нет. Это уж ты обоснуй, раз уж утверждаешь, что таймерами можно синхронизировать доступ меж потоками. Можешь даже сослаться на что-нибудь.


 
Palladin ©   (2008-06-17 19:52) [22]


> Тын-Дын ©   (17.06.08 19:11) [21]

:) смешной... таймеры частный случай 2.б., только вместо отдельного монитора потока на форму кидаются таймеры, или один таймер, но с опросом всех потоков.

интересно, где же ты решил что с использованием таймеров КС не понадобятся...


 
Тын-Дын ©   (2008-06-17 22:09) [23]


> 2.б либо реализовать доп.поток, сборщик данных, аналог таймера,
>  который с определенным интервалом будет синхронизировать
> собранные данные с главным потоком приложения



> 2.а либо реализовать на основе таймеров забор значений,
> но он мне не нравится



> :) смешной... таймеры частный случай 2.б.,


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

Плодить дополнительный поток для сбора данных, необходимых основному потоку - бред.

Правильное решение - использовать критические секции для чтения данных из доп. потоков.


> Leonid Troyanovsky ©   (17.06.08 18:18) [17]
>Если все
> изменения становятся доступны первичному потоку,то какая
> нах разница - он волен в проявлении своей инициативы,работая
> со своей копией данных.Синхронизацию через SendMessage окну
> первичного потока пользовалираннии версии дельфи, и особого
> криминала здесь замечено не было, за исключением некоторых
> вырожденных случаев.


А разница в том, что основному потоку в определенный момент времени нужны данные, а не произвольно поступающие от потоков посредством SendMessage.


 
Тын-Дын ©   (2008-06-17 22:10) [24]

Вообще не могу понять, причем здесь таймеры? На кой они ляд?
Собаке пятая нога, чтобы жизнь сладкой не казалась?
Бредятина.


 
ANB   (2008-06-17 22:21) [25]


> А разница в том, что основному потоку в определенный момент
> времени нужны данные, а не произвольно поступающие от потоков
> посредством SendMessage.

Обработчик их складет в буфер. Когда основному потоку встеблится их пользовать - оттуда и достанет.


> Вообще не могу понять, причем здесь таймеры? На кой они
> ляд?

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

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


 
Тын-Дын ©   (2008-06-17 22:26) [26]


> Обработчик их складет в буфер. Когда основному потоку встеблится
> их пользовать - оттуда и достанет.


И? Чем это отличается от чтения из основного потока?


> Если основной поток мониторит ход работы доп.потоков то
> таймер на опросе - самое простое решение.


В условии нет никаких таймеров. Предлагается какое-то решение с таймерами. Для чего?


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


Неважно, КАК работают потоки.
Есть некий факт - нужно в неопределённый момент времени получить от каждого потока данные.

Никаких проблем не возникнет в случае синхронизации. Никакой потери преимуществ. Да и странно было бы, если бы было иначе.


 
oxffff ©   (2008-06-17 22:35) [27]


> Leonid Troyanovsky ©   (17.06.08 13:16) [9]
>
> > vint45   (17.06.08 12:42)  
>
> > Вопрос. Надо ли помещать в критическую секцию процесс
> чтения
> > локальных переменных главным потоком из остальных потоков?
>
>
> Любое обращение к перменной из любого потока должно идти
> через КС.
> Либо через InterLocked*. Либо из вторичных потоков через
> Synchronize.
>
> --
> Regards, LVT.


Ссылочку на должествование не приведете?
Поток чтения может обращаться к shared данным напрямую.

Для многоядерного(односокетного) компьютера нет необходимости  использования InterLocked* функций в потоках записи.

Для многосокетного компьютера можно натолкнуться на
Synchronization and Multiprocessor Issues в случае, если есть зависимое чтение. То есть на основе анализа состояния одних данных извлекать другие. В MSDN есть пример. Тогда действительно любые инструкции процессора с Lock префиксом (InterLocked* WIN 32 API).
Если нет зависимого чтения, то InterLocked* не нужны.

Это все естественно для случая когда вы читаете сырые данные без привязки к какому либо моменту.


 
ANB   (2008-06-17 22:38) [28]


>
> И? Чем это отличается от чтения из основного потока?

Тем что чтение мона проводить незащищенно. А запись из доп.потоков синхронизнет ОС.


> В условии нет никаких таймеров. Предлагается какое-то решение
> с таймерами. Для чего?

Для удобства. А если не надо мониторить работу потоков - зачем вообще куда то что то из потоков писать ?


> Никаких проблем не возникнет в случае синхронизации. Никакой
> потери преимуществ. Да и странно было бы, если бы было иначе.
>

Проблем - не возникнет. Просто если потоки только считают что то толстое на своем компе, то скорость многопоточного расчета будет как минимум не быстрее, чем в одном потоке. Это и будет потерей преимущества.


 
Тын-Дын ©   (2008-06-17 22:45) [29]


> Тем что чтение мона проводить незащищенно.


Нельзя.


> > В условии нет никаких таймеров. Предлагается какое-то
> решение > с таймерами. Для чего?Для удобства. А если не
> надо мониторить работу потоков - зачем вообще куда то что
> то из потоков писать ?


В чём удобство - поясни?


> Проблем - не возникнет. Просто если потоки только считают
> что то толстое на своем компе, то скорость многопоточного
> расчета будет как минимум не быстрее, чем в одном потоке.
>  Это и будет потерей преимущества.


о чём разговор? Про доп. потоки что-то известно было?
Весь вопрос - надо получить данные и нужно ли синхронизировать.

Ответ - ДА. Как? Критическими секциями.


 
Тын-Дын ©   (2008-06-17 22:47) [30]


> Поток чтения может обращаться к shared данным напрямую.


Не может.


 
oxffff ©   (2008-06-17 22:49) [31]


> Тын-Дын ©   (17.06.08 22:47) [30]
>
> > Поток чтения может обращаться к shared данным напрямую.
>
>
>
> Не может.


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

Это все естественно для случая когда вы читаете сырые данные без привязки к какому либо моменту.
Может. :)


 
Тын-Дын ©   (2008-06-17 23:00) [32]


> Это все естественно для случая когда вы читаете сырые данные
> без привязки к какому либо моменту.


Тогда давай подробнее про сырые данные.
Что это такое?


 
oxffff ©   (2008-06-17 23:08) [33]


> Тын-Дын ©   (17.06.08 23:00) [32]


Если один поток пишет данные(вычисляет) , а второй только читает(отображает на экране).
Зачем делать синхронизацию, если данные актуальные на момент чтения.
Если нет требований к привязки к моменту(очередности), то данные которые были между двумя моментами чтения можно пропустить.
Это случай когда данные пишутся не в очередь, а просто расположены в Shared переменных. И если они отображаются на экране, то поток чтения может просто считывать их 25 раз в секунду, более не нужно.


 
oxffff ©   (2008-06-17 23:11) [34]


> Тын-Дын ©   (17.06.08 23:00) [32]
>
> > Это все естественно для случая когда вы читаете сырые
> данные
> > без привязки к какому либо моменту.
>
>
> Тогда давай подробнее про сырые данные.
> Что это такое?


Читал вопрос внимательно?

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


 
ANB   (2008-06-17 23:25) [35]


> > Тем что чтение мона проводить незащищенно.
>
>
> Нельзя.

Почему ? Пишет в этот буфер главный поток (обработчиком сообщения), читает он же.


> В чём удобство - поясни?

Писать меньше - в обработчик таймера засунул визуализацию и всех делов.

При этом главная форма висеть не будет.


> oxffff ©   (17.06.08 23:08) [33]

Чет я не понял. Можно безопасно без всякой синхронизации читать одним потоком кусок памяти, в который одновременно что то пишет другой поток ?


 
MsGuns ©   (2008-06-17 23:33) [36]

Чем дальше в лес, тем толще партизаны. Синхронизация не является необходимой, например, в таком случае.
Приложение предусматривает запуск длительного многошагового расчета чего-нибудь. При этом сам расчет выполняется в N шагов и может быть завершен одним из след. способов:
- нормальное завершение
- ошибка на сервере
- ошибка при обработке данных на клиенте (например, несоответствие данных или по памяти)
- прервано пользователем.

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

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

"Опрос" гл.потоком реализован банально - через 1 сек. просматривается очередь активных потоков (через список и объекты-рекорды как было указано выше) и анализируется соотв. поле рекорда - статусное. В зависмости от его состояния (а его изменяет сам поток без всякой синхронизации) - в сетке рисуется соотв. иконка. Если поток завершен, то из списка активных указатель не его рекорд переносится в список завершенных (прерванных) и сетка завершенных перерисовывается. При  этом если поток "не успеет" записать в статус новое значение и в сетке не отрисуется новая иконка, то это совершенно некритично - через секунду все актуализируется, а пользователь даже не успеет заметить, особенно если число активных процессов у него несколько десятков.
Я описал совершенно реальную абсолютно работающую схему, и попрошу объяснить, какого лешего я должен эту "тупую" не синхронную схему с опросом заменять на хитрозадую, основанную на требовании каждого потока при изменении его статуса перерисовывать что-то там в гл.потоке в режиме строгой синхронизации ? Чтобы код соответствовал "высоким технологиям" и вумным книжкам ?


 
Тын-Дын ©   (2008-06-17 23:48) [37]


> oxffff ©   (17.06.08 23:08) [33]
> > Тын-Дын ©   (17.06.08 23:00) [32] Если один поток пишет
> данные(вычисляет) , а второй только читает(отображает на
> экране).Зачем делать синхронизацию, если данные актуальные
> на момент чтения.


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


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


Ну и? Как это притиворечит пердыдущему абзацу?


> ANB   (17.06.08 23:25) [35]


> Почему ? Пишет в этот буфер главный поток (обработчиком
> сообщения), читает он же.


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


> Писать меньше - в обработчик таймера засунул визуализацию
> и всех делов.При этом главная форма висеть не будет.


Ну никак по таймеру невозможно данные синхронизировать. Основной поток должен их получить в произвольный момент времени. Например, при нажатии пользователем на кнопку.


> MsGuns ©   (17.06.08 23:33) [36]


> Чтобы код соответствовал "высоким технологиям" и вумным
> книжкам ?


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


> анализируется соотв. поле рекорда - статусное.


Ты забыл сказать про тип этого поля.
В случае Boolean запись проходит атомарно.
Если у тебя в поле целое число или строка, то глюки неизбежны.
Хотя при Integer современные процессоры вроде бы теперь тоже атомарно операции выполняют(присвоение).


 
ANB   (2008-06-17 23:50) [38]


> В зависмости от его состояния (а его изменяет сам поток
> без всякой синхронизации)

Прямой записью в память, которую периодически читает главный поток ?

Чет я отстал от жизни.


 
ANB   (2008-06-17 23:54) [39]


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

Поток изменил данные - послал сообщение, данные в буфере поменялись.

Кнопочка и таймер - не противоречат друг другу.

А согласованность данных при многопоточных вычислениях - тады уж лучше и не устраивать многопоточность.


 
Тын-Дын ©   (2008-06-17 23:56) [40]


> Поток изменил данные - послал сообщение, данные в буфере
> поменялись.


Так ещё раз - данные нужны основному потоку иногда.
Если получение данных будет происходить по инициативе доп. потоков, да ещё и массовым спамом сообщениями в основной поток, то основной поток совсем захлебнётся их обработкой. Я не прав?



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

Форум: "Начинающим";
Текущий архив: 2008.07.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.59 MB
Время: 0.049 c
2-1213676469
affonya
2008-06-17 08:21
2008.07.20
Процессы в фоне


15-1211970166
Randew
2008-05-28 14:22
2008.07.20
Вредно ли мышке постоянно "светится"?


1-1195571102
авыф
2007-11-20 18:05
2008.07.20
Компоненты DevExpress


15-1212666482
ЧуВАГ
2008-06-05 15:48
2008.07.20
Delphi uses


15-1212611640
Максим В.
2008-06-05 00:34
2008.07.20
TCP





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