0 / 0 / 0
Регистрация: 18.02.2014
Сообщений: 5
1

Обмен данными между потоками

18.02.2014, 17:59. Показов 8676. Ответов 29
Метки нет (Все метки)

Здравствуйте уважаемые форумчане!
Реализую многопоточное приложение. Один поток в реальном времени читает данные с USB и пишет их в массив (массив большой, 256*65536), второй должен эти данные обрабатывать (нарезать на другие массивы, поменьше, что-то делать с ними, результат складывать в финальный массив), третий занимается тем, что выводит финальный массив на Panel. Потоки делаю не CreateThread, а TThread, ради VCL-компонентов.
Вопрос вот в чем: как реализовать обмен данными между потоками? Иными словами, как первый большой массив передать из 1го потока во 2ой и как передать последний массив из 2го потока в 3й? С классами на данный момент знаком очень поверхностно, раньше только с функциями работал.
Заранее спасибо за помощь!
0

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

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.02.2014, 17:59
Ответы с готовыми решениями:

Обмен данными между компьютером и ПЛК по TCP
Добрый день! Подскажите пожалуйста, реально ли написать программу на C++ Builder для получения...

Обмен данными между RAD Studio Berlin и cmd
Всем привет. Как реализовать обмен данными между C++ и cmd. Отправляю команду в консоль, а из...

Обмен данными между программой и сервисом через NamedPipe
Всем доброго времени суток. Друзья, у меня такая проблема: Создаю сервис, на OnExecute создаю...

Обмен данными между C++ Builder и Java компонентами socket-ов
Всем доброго времени суток. Не знаю, следует-ли создавать эту тему именно в данном разделе, т.к....

29
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
18.02.2014, 19:46 2
Через объекты синхронизации.
0
435 / 402 / 57
Регистрация: 06.02.2012
Сообщений: 1,384
19.02.2014, 04:21 3
Иметь общий массив, который будет видится со всех потоков не проблема (например глобальная переменная), но это не главное.
Делаем два буферных массива. Пока 1ый поток пишет в 1ый буфер, 2ой поток обрабатывает второй массив, затем меняются местами.
Нужно смотреть в сторону event-ов http://www.firststeps.ru/mfc/winapi/r.php?119
Я бы сказал, синхронизация потоков это задача не для новичка.
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
19.02.2014, 08:46 4
Еще один вариант: первый поток заполняет здоровый массив и в конце заполнения выбрасывает флаг. Второй поток ждет этого флага и, получив его, заполняет свои маленькие массивы. По окончанию заполнения выбрасывает так же свой флаг. По флагу второго потока первый убирает свой и готовится к приему новой порции данных. В то же время, третий поток, видя флаг второго начинает вывод маленьких массивов.
Так как потоки не изменяют данные друг друга, а только читают их, то можно обойтись без серьезной синхронизации.
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
19.02.2014, 12:30 5
Цитата Сообщение от gumi250 Посмотреть сообщение
Я бы сказал, синхронизация потоков это задача не для новичка.
Тогда чЁ мелочится: потоки- это не для новичка... ибо одно без другого не работает ...

Добавлено через 2 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
ак как потоки не изменяют данные друг друга, а только читают их, то можно обойтись без серьезной синхронизации.
А выбрасывание флага это не синхронизация?
Если данный только читаются это не означает что их не нужно синхронизировать.
0
0 / 0 / 0
Регистрация: 18.02.2014
Сообщений: 5
19.02.2014, 13:07  [ТС] 6
SatanaXIII, то есть будет достаточно сделать большой массив глобальной переменной, писать в него в 1м потоке, но запретить изменять её во 2 потоке (аналогично и для потоков 2 и 3) и добавить пару флагов, которые сообщал бы следующему потоку, что данные можно забирать?
Я как-то так и предполагал, но меня это смущает только тем, что глобальные переменные присущи С, в С++ рекомендуется их всячески избегать. В принципе, я понимаю, что если внимательно проследить, чтобы два класса не меняли данные одновременно, то ничего страшного нет, но думал, что есть какой-то более правильные метод обмена данными.
gumi250, в вашем варианте не может быть такого, что первый поток хочет писать данные, но второй ещё не закончил обработку и не дает ему это делать, из-за чего данные теряются?

Ещё один вопрос: мою задачу можно реализовать на таймерах TTimer, не связываясь с потоками. Насколько это решение хуже/лучше/правильней/неправильней потоков? Не смог найти никакой информации об этом.
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
19.02.2014, 13:45 7
Цитата Сообщение от Avazart Посмотреть сообщение
А выбрасывание флага это не синхронизация?
Именно что синхронизация. Только врукопашную. Безусловно, правильно использовать стандартную отлаженную синхронизацию, как вы и предлагали. По этому я и говорю, что лишь еще один вариант. Если хочется, почему бы и нет?
Цитата Сообщение от Avazart Посмотреть сообщение
Если данный только читаются это не означает что их не нужно синхронизировать.
Тут не нужен будет еще один синхронизирующий механизм, или дополнительная структура, чтоб ее между потоками передавать. Все потоки будут сами себя изменять. Но с оглядкой на другие. Главное все правильно спланировать.
Можно не выставлять флаги, а, как предлагает gumi250, отсылать сообщения. Вариантов куча.
Цитата Сообщение от super1337coder Посмотреть сообщение
то есть будет достаточно сделать большой массив глобальной переменной, писать в него в 1м потоке, но запретить изменять её во 2 потоке (аналогично и для потоков 2 и 3) и добавить пару флагов, которые сообщал бы следующему потоку, что данные можно забирать?
Ну типа того. Только не просто запретить изменять следующим потоком данные предыдущего, а вообще никак никогда даже и не пытаться.
Цитата Сообщение от super1337coder Посмотреть сообщение
глобальные переменные присущи С, в С++ рекомендуется их всячески избегать
Это тема для целого отдельного большого холивара. Х) В целом да, рекомендуется их делать минимум членами класса (потока в вашем случае).
Цитата Сообщение от super1337coder Посмотреть сообщение
внимательно проследить, чтобы два класса не меняли данные одновременно
Вот вы и попались. Только один поток может менять какие-то конкретные данные. Второй только читать.
Цитата Сообщение от super1337coder Посмотреть сообщение
есть какой-то более правильные метод обмена данными
Вот вы и пришли к тому, о чем вам сказал Avazart прям первым ответом. Берете какие-нибудь мьютексы, семафоры или критические секции - на выбор, и осуществляете синхронизацию по человечески.
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
19.02.2014, 14:29 8
Цитата Сообщение от super1337coder Посмотреть сообщение
SatanaXIII, то есть будет достаточно сделать большой массив глобальной переменной, писать в него в 1м потоке, но запретить изменять её во 2 потоке (аналогично и для потоков 2 и 3) и добавить пару флагов, которые сообщал бы следующему потоку, что данные можно забирать?
Термин флаг не уместен он только запутывает, не флаг а объект синхронизации.
Объект синхронизации можно рассматривать как флаг, но не наоборот. Объект синхронизации должен гарантировать атамарность операции.

Добавлено через 3 минуты
Цитата Сообщение от super1337coder Посмотреть сообщение
Я как-то так и предполагал, но меня это смущает только тем, что глобальные переменные присущи С, в С++ рекомендуется их всячески избегать.
Именно так, все верно.
Но правильнее сформулировать это так: переменная должна быть максимально локальной, насколько это возможно.

Добавлено через 4 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
В целом да, рекомендуется их делать минимум членами класса (потока в вашем случае).
Ни данные ни объект синхронизации, никакого отношения не имеют к потоку ( в данном случае потокам) почему они должны быть членами его класса ?

Добавлено через 6 минут
Цитата Сообщение от super1337coder Посмотреть сообщение
Один поток в реальном времени читает данные с USB и пишет их в массив (массив большой, 256*65536), второй должен эти данные обрабатывать (нарезать на другие массивы, поменьше, что-то делать с ними, результат складывать в финальный массив),
Почему сразу не читать и резать ?
Зачем тут два потока?
Почему нельзя сразу читать данные "маленькими массивами" и помещать в двухмерный массив или вектор?
Существование третьего потока тоже сомнительно, но тут зависит от динамики, и способа вывода.
0
435 / 402 / 57
Регистрация: 06.02.2012
Сообщений: 1,384
19.02.2014, 16:21 9
Цитата Сообщение от super1337coder Посмотреть сообщение
gumi250, в вашем варианте не может быть такого, что первый поток хочет писать данные, но второй ещё не закончил обработку и не дает ему это делать, из-за чего данные теряются?
В моем варианте всегда пишется в один буфер, а в это время обрабатывается другой буфер. Т.е. один для записи, другой для чтения. Если комп не успевает обрабатывать поток данных, то в любом случае настанет затык так или иначе.
Один большой буфер который помнит ВСЕ данные от начала до конца при большом потоке быстро заполнится.

Добавлено через 4 минуты
Да Avazart прав, флагом не должна быть просто переменная, чтобы второй поток не крутил цикл в ожидании когда выставится этот флаг. Второй поток должен засыпать до выставления флага..
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
20.02.2014, 08:32 10
Avazart, gumi250, короче вы хотите сказать, что осуществить синхронизацию посредством изменения потоком своих же данных невозможно?
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
20.02.2014, 13:01 11
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Avazart, gumi250, короче вы хотите сказать, что осуществить синхронизацию посредством изменения потоком своих же данных невозможно?
Это как ? Ты сам понял что сказал ?
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
20.02.2014, 13:14 12
Цитата Сообщение от Avazart Посмотреть сообщение
Это как ?
Поток изменяет свою переменную, изменения которой ждет другой поток.
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
20.02.2014, 13:17 13
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Поток изменяет свою переменную, изменения которой ждет другой поток.
Сразу две траблы:

1. Откуда второй поток знает что первый не завершил работу и перестал существовать в месте со своей флаговой переменной? Что говорит о непродуманности реализации.
2. На каких основаниях мы полагаемся на атомарность этой переменной?

Поток и и данный нужно хранить отдельно, и на данные "вешать замок" в виде объекта синхронизации.
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
20.02.2014, 13:21 14
Цитата Сообщение от Avazart Посмотреть сообщение
Сразу две траблы
1) Ответственность на программисте.
2) Только один поток может изменить эту переменную.
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
20.02.2014, 13:23 15
Цитата Сообщение от SatanaXIII Посмотреть сообщение
1) Ответственность на программисте
А Вы кто ? Прохожий ?
Цитата Сообщение от SatanaXIII Посмотреть сообщение
2) Только один поток может изменить эту переменную.
А второй прочитать, и?

Один может не успеть изменить, а второй успеть прочитать "недоизмененное", еще раз вы читать не умеете слово атомарность ?

http://ru.wikipedia.org/wiki/%... 0%B8%D1%8F
0
Почетный модератор
Эксперт С++
5843 / 2852 / 390
Регистрация: 01.11.2011
Сообщений: 6,903
20.02.2014, 13:33 16
Цитата Сообщение от Avazart Посмотреть сообщение
А второй прочитать, и?
И поменять свою.

Цитата Сообщение от Avazart Посмотреть сообщение
а второй успеть прочитать "недоизмененное"
И что? Он ничего не делает, получая недоизммененное. У него четкое условие: если-то, а не: если что-то там где-то изменилось, то надо что-то срочно предпринимать.
0
435 / 402 / 57
Регистрация: 06.02.2012
Сообщений: 1,384
20.02.2014, 14:02 17
Цитата Сообщение от Avazart Посмотреть сообщение
Один может не успеть изменить, а второй успеть прочитать "недоизмененное", еще раз вы читать не умеете слово атомарность ?
Я полагаю, что кривенько (но работоспособно) реализовать флаги для закрытия общей переменной для всех потоков кроме одного можно и без объектов синхронизации (чтобы не было чтения изменяемой переменной). Но вот во время ожидания выставления этих флагов в потоках придется крутить циклы, что или приведет к большим ресурсозатратам или потере атомарности (если вставить в циклы Sleep(1) )
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
20.02.2014, 14:34 18
Цитата Сообщение от SatanaXIII Посмотреть сообщение
И что? Он ничего не делает, получая недоизммененное. У него четкое условие: если-то, а не: если что-то там где-то изменилось, то надо что-то срочно предпринимать.
Поток получит порченные,некорректные данные, вы понимаете что значит? О каких условиях может быть речь?
Цитата Сообщение от gumi250 Посмотреть сообщение
Я полагаю, что кривенько (но работоспособно) реализовать флаги для закрытия общей переменной для всех потоков кроме одного можно и без объектов синхронизации (чтобы не было чтения изменяемой переменной). Но вот во время ожидания выставления этих флагов в потоках придется крутить циклы, что или приведет к большим ресурсозатратам или потере атомарности (если вставить в циклы Sleep(1) )
Игры с огнем, или другим словом чудо-код.
0
435 / 402 / 57
Регистрация: 06.02.2012
Сообщений: 1,384
20.02.2014, 14:53 19
Цитата Сообщение от Avazart Посмотреть сообщение
Игры с огнем, или другим словом чудо-код.
Бывает не практичный чисто академический интерес.
Цитата Сообщение от Avazart Посмотреть сообщение
Поток получит порченные,некорректные данные, вы понимаете что значит? О каких условиях может быть речь?
У ТС маловероятно. У ТС менять буфер будет только один поток, второй только читать. Причем подразумевается что прцесс чтения быстрее записи. Второй поток ждет пока первый выставит флаг что запись готова, и только потом начинает чтения.
0
Эксперт С++
8372 / 6108 / 613
Регистрация: 10.12.2010
Сообщений: 28,517
Записей в блоге: 30
20.02.2014, 14:58 20
Цитата Сообщение от gumi250 Посмотреть сообщение
Бывает не практичный чисто академический интерес.
Для академичекого интереса лучше книги почитать.
Цитата Сообщение от gumi250 Посмотреть сообщение
Причем подразумевается что прцесс чтения быстрее записи.
C потоками такие допущения делать нельзя.
Цитата Сообщение от gumi250 Посмотреть сообщение
У ТС менять буфер будет только один поток, второй только читать.
Как это меняет дело?
Обращение к данным идет из разных потоков ?
-Да, значит это разделяемый ресурс.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.02.2014, 14:58

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

Обмен данными по сети интернет
Возник такой вопрос, каким образом можно оганизовать обмен данными между двумя программами по сети...

ServerSocket и ClientSocket обмен данными
Подскажите как обмен данными идет через SendText и ReceiveText в данных компонентах (ServerSocket и...

Обмен данными через COM порт
Доброго времени суток. Требуется производить обмен данными с неким устройством через СОМ порт....

Обмен данными через интернет
Доброго времени суток!!! При помощи чего реализовать обмен данными между компьютерами через...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.