![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как избежать гонок в потоках [D6, WinXP]
leonidus © (2005-05-31 10:38:00)Мастера подскажите пожалуйста. Я написал небольшую программу, она скачивает новости с разных сайтов, и затем парсит каждую скачанную страницу на предмет нужной информации. Т.е. программа состоит из бвух блоков - блок закачки (качается сразу в несколько потоков, для каждой страницы с новостями свой поток) и блок парсинга (в нем также предусмотрена многопоточность, при этом для каждой скачанной страницы должен запускаться свой экземпляр одного и тогоже потока). Результаты парсинга (заголовки новостей) помещаются в массив. И вот в чем проблема. Если одновременно скачаются две страницы и одновременно начнут работать два парсера, то может так получиться, что они будут обращаться к одному элементу массив, что бы записать в него полученный заголовок новости. Т.е. я тап понимаю это ситуация гонок. Подскажите как этого избежать. Может есть какие-то статьи по этому поводу, я что-то ничего толком не нашел. Заранее спасибо.
leonidus (2005-06-03 08:27:00) [1]Блин вот это тред мы тут развели:) Может действительно усложнили задачу... в начале все так элегантно получалось. Я одного не пойму, если критическая секция априори допускает в себя только один поток, то значит мы этим механизмом однозначно не допустим параллельной записи и одновременного чтения из массива, что нам собственно и нужно. Но тут накладывается проблема чтения массива в произвольный момент времени. Ну так она должна решаться просто повышением приоритета читающего потока над записывающим. Т.е. если записывающий (W) уже в секции, читающий(R) все равно бессилен, но зато когда W закончит свою работу управление передасться R а не следующему W, а считав нужные данные W передаст эстафету следующему R что и требовалось доказать. Я правильно мыслю?
Alexander Panov (2005-06-02 23:17:00) [2]GrayFace © (02.06.05 21:40) [85]
Поддерживаю.
Аналогично, как и перед этим. В топике в потрепаловке есть где разгуляться.
GrayFace (2005-06-02 21:40:00) [3]evvcom © (02.06.05 8:51) [65]
Поэтому в пишущем потоке я бы даже synchronize не стал вызывать, а использовал бы PostMessage.
Поддерживаю.
GrayFace (2005-06-02 21:28:00) [4]leonidus
См. книгу Рихтера "Windows для профессионалов". По слухам, есть на http://www.podgoretsky.com
evvcom (2005-06-02 17:20:00) [5]Перенес http://www.delphimaster.ru/cgi-bin/forum.pl?id=1117717481&n=3
Alexander Panov (2005-06-02 15:55:00) [6]Прошу прощения за резкое высказывание.
Предлагаю перенести дискуссию в потрепаловку.
Alexander Panov (2005-06-02 15:41:00) [7]evvcom © (02.06.05 13:54) [79]
...Во время оповещения читающий поток ждет, когда ему ОС выделит квант времени. :)
...И после того как пишущий делает свое дело, он извещает об этом читателя.
...мне нравится PostMessage, хотя по ситуации
Еще раз.
1. Если ожидающий поток ждет кванта времени, это означает, что он не назодится в сотоянии ожидания одного из объектов ядра?
2. Нахрена извещать поток, если он всего лишь "ожидает кванта времени"?
3. С какого перепугу поток вдруг начнет обрабатывать PostMessage?
---------------------
Может хватит чушь нести?
Erik1 (2005-06-02 15:17:00) [8]Всегда тут не по теме треплются.
Автору
Советую обратить внимание на группу функций WaitFor(MultiObject). Для опредерения необходимости запуска потоков. Допустим такую ситуацию, пишуший поток вошол в критическаю секцию и завис на обашении к сети. Вся наша система встала, даже трудно понять, что произошло. Для облегчения взвимодействия потоков применяются события и функции ожидающие этих событий. Причем событий может быть несколько, например сигнал аваийного звершения задачи.
P.S
Свой код могу выложить или выслать по почте.
evvcom (2005-06-02 13:54:00) [9]
> Как извещает?
мне нравится PostMessage, хотя по ситуации
> И что делает в это время читающий поток?
Во время оповещения читающий поток ждет, когда ему ОС выделит квант времени. :)
> не кажется ли вам.
Мне это уже давно кажется. Надо завязывать.
Alexander Panov (2005-06-02 13:19:00) [10]evvcom © (02.06.05 12:50) [76]
И после того как пишущий делает свое дело, он извещает об этом читателя.
Как извещает? И что делает в это время читающий поток?
Digitman (2005-06-02 12:55:00) [11]
> Alexander Panov
> evvcom
не кажется ли вам. уважаемые судари, что сабж перешел в статус "мерянье концами" ?)
evvcom (2005-06-02 12:50:00) [12]
> А читающий поток?
А что читающий поток? Ни один из потоков не захватывает время настолько, чтобы заметно мешать другим потокам. И после того как пишущий делает свое дело, он извещает об этом читателя. Это гарантирует, что читающий обработает все данные.
> Любая мелочь может сыграть роковую роль для приложения.
С этим полностью согласен.
Alexander Panov (2005-06-02 12:29:00) [13]>evvcom ©
При проектировании многопоточного потока не бывает мелочей, на которые не стоит обращать внимание.
Любая мелочь может сыграть роковую роль для приложения.
-------------
PS.
А потом говорим, что приложение падает непонятно почему.
Alexander Panov (2005-06-02 12:26:00) [14]evvcom © (02.06.05 12:19) [73]
По-моему, мы углубились в такие дебри и пытаемся раздуть из мухи слона там, где проблема выеденного яйца не стоит. Все имхо.
Это не дебри.
Это элементарная тщательность при проектировании многопоточного приложения.
То, что запись происходит бысто - это не аргумент.
evvcom © (02.06.05 12:19) [73]
Здесь нет этой проблемы, Имхо. И здесь потоки держат критическую секцию не по 1 секунде. Даже у сотни потоков на разовую запись уйдет меньше секунды.
А читающий поток?
evvcom (2005-06-02 12:19:00) [15]
> А я не увидел предложенного решения от тебя(методологии,
> алгоритм). Или я что-то упустил?
Предложения не сформулированы в одном моем посте, это надо перечитывать все обсуждение. А алгоритм подправленный всеми автор выложил в итоге сам (тоже в нескольких постах).
> А проблему с захватом процессорного времени одним потокм
Здесь нет этой проблемы, Имхо. И здесь потоки держат критическую секцию не по 1 секунде. Даже у сотни потоков на разовую запись уйдет меньше секунды.
По-моему, мы углубились в такие дебри и пытаемся раздуть из мухи слона там, где проблема выеденного яйца не стоит. Все имхо.
Alexander Panov (2005-06-02 11:52:00) [16]evvcom © (02.06.05 11:30) [71]
Так ведь есть вариант с понижением приоритета. О нем, кажется, Игорь упомянул. И все же я не увидел объяснения целесообразности употребления доп. флажков (семафора, мьютекса) в данном примере.
А я не увидел предложенного решения от тебя(методологии, алгоритм). Или я что-то упустил?
Применение объектов синхронизации(мьютексов, событий, семафоров) в классе данных задач - с арбитражем конкурирующих за ресурс потоков(несколько писателей, один читатель, или подобных) - стандартный прием.
А проблему с захватом процессорного времени одним потокм ты уже решил?
evvcom (2005-06-02 11:30:00) [17]
> > Ты разве еще не понял, что читающий поток может вообщене
> > получить управления?
> evvcom © (02.06.05 10:05) [69]
> Пальцем можно ткнуть, что помешает?
>
> Достаточно простого примера.
C примером согласен. Но если
> программа просто будет терминирована недождавшимся ответа
> пользователем
то это уже форс-мажор, и этим я бы не стал все же объяснять выражение " вообщене получить управления". А чтобы не нервировать пользователя, я уже писал, что крит.секциями стоит защищать быстро выполняемые куски кода, чтобы не тормозить работу остальных потоков, использующих эти же данные. В примере автора запись происходит всего в 2 строчках кода, их мы и защищаем. Аналогично с чтением.
> поток с повышенным приоритетом будет использовать максимально
> возможное количество времени процессора, что приведет к
> "голоданию" остальных потоков
Так ведь есть вариант с понижением приоритета. О нем, кажется, Игорь упомянул. И все же я не увидел объяснения целесообразности употребления доп. флажков (семафора, мьютекса) в данном примере.
Alexander Panov (2005-06-02 10:57:00) [18]evvcom © (02.06.05 10:05) [69]
Пальцем можно ткнуть, что помешает?
Достаточно простого примера.
У тебя сотня потоков. Из них один читающий, 99 пишущих.
Предположим, для записи каждому пишущему потоку нужно 1 сек.
Все потоки запросили критическую секцию.
В какой момент читающий поток сможет получить эту критическую секцию?
Ответ такой - это неизвестно. он может начать выполняться сразу, а может и через минуту.
Но возможно через минуту его действия уже потеряют актуальность, и программа просто будет терминирована недождавшимся ответа пользователем.
Но я нигде не встречал и того, что семафоры и мьютексы помогают "выбрать нужный поток для приоритетного выполнения". Для этого меняют приоритет самого потока. Можно и здесь пальцем ткнуть, если считаешь, что я не прав. Обсудим.
А никто и не говорил, что объекты синхронизации изменяют приоритеты. Они лишь помогают выстроить логику программы так, как нужно тебе.
Установка приоритета гарантирует тебе то, что нужный поток будет получать больше квантов времени для выполнения.
Причем повышенный приоритет потока может тебе "помочь" наоборот.
В данном конкретном случае без использования объектов синхронизации поток с повышенным приоритетом будет использовать максимально возможное количество времени процессора, что приведет к "голоданию" остальных потоков.
evvcom (2005-06-02 10:05:00) [19]
> Ты разве еще не понял, что читающий поток может вообще не
> получить управления?
Пальцем можно ткнуть, что помешает?
> Затем, что критическая секция не поможет тебе выбрать нужный
> поток для приоритетного выполнения.
Но я нигде не встречал и того, что семафоры и мьютексы помогают "выбрать нужный поток для приоритетного выполнения". Для этого меняют приоритет самого потока. Можно и здесь пальцем ткнуть, если считаешь, что я не прав. Обсудим.
Digitman (2005-06-02 09:45:00) [20]
> Alexander Panov © (01.06.05 23:10) [63]
> На память не помню, имеет ли основной поток равные приоритеты
> с дополнительными
имеет.
основной создается системой с THREAD_PRIORITY_NORMAL по дифолту
дополнительные, если не приложить свои шаловливые ручки к потрохам CreateThread, создаются с тем же приоритетом по дифолту
The thread is created with a thread priority of THREAD_PRIORITY_NORMAL (цитата из справки к CreateThread)