Форум: "Основная";
Текущий архив: 2003.05.26;
Скачать: [xml.tar.bz2];
ВнизПо поводу потоков... Найти похожие ветки
← →
tovSuhov (2003-05-15 11:36) [0]Господа, может кто разъяснит, в чем была ошибка.
Суть вот в чем - в программе создаю объекты - наследники от (TThread). Причем один поток - это некий Менеджер, который в свою очередь создает n потоков - Рабочих.
Так вот, в Менеджере перед созданием потока-Рабочего я динамически (new)выделяю буфер, указатель на этот буфер передаю рожденному потоку и оправляю его "работать". После отработки поток заносит в этот буфер полученные в процессе работы данные.
Теперь самое интересное - когда создается только один Рабочий - все проходит тип-топ. Если их несколько, то программа вываливается с ошибками типа "BORLNDMM - ошибка доступа". В процессе отладки выяснил, что возникает она только тогда, когда Рабочие пишут в этот самый буфер.
Замечу сразу - указатели передаю разные, и ситуация одновременной записи потоками в один и тот же буфер исключена. Также исключена ситуация записи потоком в буфер данных, размер которых больше, нежели было выделено Менеджером.
Проблему обошел следующим образом - в Менеджере жду завершения работы всех рожденных потоков, и потом последовательно от каждого из них "сливаю" данные.
Интересует чисто теоретический аспект - какие могут быть причины некорректной работы описанного выше алгоритма?
С уважением, Сергей.
← →
Dms (2003-05-15 11:40) [1]попробуй перейти на D7
← →
Palladin (2003-05-15 11:45) [2]проблема одновременного доступа к данным, больше ничего...
кто знает чего ты там написал до этого... кода нет... больше добавить нечего...
← →
evvcom (2003-05-15 11:56) [3]У меня менеджер сидит в основном потоке, т.е. там же, где и вся рисовательно-отзывающаяся часть. Менеджер не требует много времени для своей работы, так какой тогда смысл выносить его в отдельный поток?
Далее код создания и завершения рабочего потока также выполняется в основном. Итоговые данные из внутренних структур переписываются в основные в завершающем коде потока. Это гарантирует синхронизацию. И лишь кое-где в Execute у меня возникала необходимость обращаться к основным данным и тоже вроде никто другой не должен был к ним обращаться. Тоже были некоторые проблемы. Пришлось до минимума сократить подобные обращения, а где не было возможности использовал объекты синхронизации. Проблемы исчезли.
← →
tovSuhov (2003-05-15 12:02) [4]Так а что подразумевать по одновременным доступом к данным?
Хорошо, приведу пример кода (правда на С++)
Поток-Менеджер:
for...
{
char * _data = new char[my_size]; //выделяю буфер
TMyWorker * _worker = new TMyWorker(_data,my_size); // создаю поток, передаю указатель на буфер
_worker->Resume(); // запускаю поток
}
Поток-Рабочий, метод Execute:
{
....
выполняется работа
....
memcpy(_data_ptr(указатель, котрый был передан в конструктор),(локальный буфер),(размер локального буфера));
//размер локального буфера либо 0, либо тот,что был передан в конструктор
};
Все. Так вот когда поток один - все ОК. Иначе глючит. По-моему никакого одновременного доступа к данным нет, или я ошибаюсь?
← →
evvcom (2003-05-15 12:11) [5]Трудно судить по куску кода. Попробуй хотя бы ввести объекты синхронизации. Исчезнет ошибка - значит однозначно собака здесь порылась.
← →
Palladin (2003-05-15 12:13) [6]а поток твой в этот _data пишет что нибудь по дороге исполнения?
← →
clickmaker (2003-05-15 12:15) [7]Очевидно, выделение памяти типа new перехватывается борландовским MM. Попробуй использовать GlobalAlloc или HeapAlloc
← →
tovSuhov (2003-05-15 12:25) [8]To Palladin:
Нет, не пишет. Сваливает только в конце работы.
To clickmaker: Я тоже подозреваю, что собака порылась в борландовом ММ. Но не понимаю каким образом.
← →
clickmaker (2003-05-15 12:29) [9]А обязательно юзать этой самый borlandmm? Не включай юнит ShareMem в свой проект и все дела. А используй АПИшные ф-ии, какие - я уже писал
← →
Alexander1966 (2003-05-15 13:28) [10]Попробуй для создания потоков использовать BeginThread
← →
Palladin (2003-05-15 13:43) [11]
> Сваливает только в конце работы.
а если в конце исполнения сливают два потока (три и более)?
уж не борятся ли они друг с другом за место в буффере?
← →
Verg (2003-05-15 13:47) [12]А какая связь между
> new TMyWorker(_data, my_size);
и
> memcpy(_data_ptr(указатель, котрый был передан в конструктор),(локальный
> буфер), (размер локального буфера));
??
Где гарантия того, что первый >= второго?
Или чего-то не договариваешь.
← →
Verg (2003-05-15 13:51) [13]Я хотел спросить: локальный буфер ты выделяешь динамически в execute потока?
← →
panov (2003-05-15 17:36) [14]Попробуй все-таки критические секции ввести...
Скорее всего, BorlandMM и твои потоки работают с одним участком памяти одновременно... Так мне кажется.
← →
tovSuhov (2003-05-15 18:41) [15]Я выделяю память, указатель на нее передаю в поток. Внутри потока эту память чем-то заполняю.
Подверждаю следующие вещи:
1. Все потоки пользуются каждый своим буфером.
2. В буфер поток либо не пишет ничего, либо пишет ровно столько байт, сколько под него выделялось.
Так вот, вопрос - ТЕОРЕТИЧЕСКИ - могут возникнуть ошибки при таком подходе или нет? Оставим глюки реализации вне темы.
← →
panov (2003-05-15 20:35) [16]>tovSuhov (15.05.03 18:41)
Я бы не дал рук на отсечение, что при использовании BorlandMM проблем не будет.
← →
Palladin (2003-05-15 21:30) [17]Да могут, именно та которую я тебе в начале описал, как уже сказал panov © (15.05.03 17:36) при использовании каких либо общих вещей для множества потоков работают с критическими секциями
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.05.26;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c