Форум: "Основная";
Текущий архив: 2009.09.13;
Скачать: [xml.tar.bz2];
ВнизDelphi+WinAPI (threads) - синхронизация переменных Найти похожие ветки
← →
LonelyWolf (2008-06-27 12:01) [0]Пишу прогу-клиент FTP на Delphi7, используя WinAPI. Прога многопоточная. Возникла интересная трабла: переменную, объвленную в общем VAR разделе используют нити. Синхронизацию потоков делаю через Events (WaitForSingleObject)... Смысл "глюка" - в одной из нитей переменной присваивается значение, устанавливается SetEvent(), которого ждет основной поток. Получив Event, проверяет эту переменную и иногда эта переменная равна нулю для основного потока... т.е. никаких данных в нее не внесено. Хотя для нити эта переменная уже равна определенному значению. В общем нить присваивает переменной значение, а главная нить его некоторое время не видит. Вопрос можно решить оператором sleep(100) или пустым циклом ожидания не нуля в переменной. Но это способы неверные, т.к. sleep(100) дает совсем уж ненужную задержку, а пустой цикл неверен сам по себе, т.к. перменная может принять любое значение.
Причем заметил что чаще всего это просиходит на многоядерном проце и редко на одноядерном.
Пробовал делать примерно так:
Нить:
[code]
EnterCriticalSection
aa:= aa+1;
LeaveCriticalSection
SetEvent(WaitForVar);
[/code]
Главная нить:
[code]
WaitForSingleObject(WaitForVar...);
...
[/code]
но этот способ не помог...
Подскажите где чего можно почитать по этому поводу чтобы грамотно соорудить нужную мне конструкцию.
Да, MultiThread переменную в дельфе я ставлю в True как советует мануал, но толку от этого ноль.
← →
clickmaker © (2008-06-27 12:15) [1]попробуй через InterlockedIncrement()
← →
Leonid Troyanovsky © (2008-06-27 13:24) [2]
> LonelyWolf (27.06.08 12:01)
> Подскажите где чего можно почитать по этому поводу чтобы
> грамотно соорудить нужную мне конструкцию.
http://www.compress.ru/Article.aspx?id=11782
--
Regards, LVT.
← →
han_malign © (2008-06-27 13:38) [3]следи за мыслью
ECS
aa
LCS
SE WFS
ECS
aa aa
... ...
если нужно четко мониторить все изменения "аа" - то это классическая задача на двух семафорах(RSE2)WFS1
aa
SE2 (RSE1)WFS2
aa
SE1
либо считывание тоже надо в критическую секцию обертывать(а иначе она вообще смысла не имеет)
InterlockedIncrement/InterlockedExchange/etc - гарантирует атомарность изменения 32-битного значения
MultiThread - "включает" критическую секцию в менеджере памяти(thread-safe Get/Free/ReallocMem, New/Dispose, создание/удалению объектов, работа со строками и динамическими массивами)...
← →
Leonid Troyanovsky © (2008-06-27 13:45) [4]
> han_malign © (27.06.08 13:38) [3]
> MultiThread - "включает" критическую секцию в менеджере
> памяти
IsMultiThread
--
Regards, LVT.
← →
oxffff © (2008-06-28 12:44) [5]
> InterlockedIncrement/InterlockedExchange/etc - гарантирует
> атомарность изменения 32-битного значения
А еще гарантирует, что все процессоры увидят обновления немедленно.
← →
oxffff © (2008-06-28 12:46) [6]
> Причем заметил что чаще всего это просиходит на многоядерном
> проце и редко на одноядерном
На одноядерном такой проблемы не должно быть.
Если есть, значит ты что-то не правильно делаешь.
Код в студию.
← →
Тын-Дын © (2008-06-28 16:33) [7]
> LonelyWolf (27.06.08 12:01)
Без кода что-либо невозможно сказать, кроме того, что у тебя реализация неверная.
> oxffff © (28.06.08 12:46) [6]
>На одноядерном такой проблемы
> не должно быть.
На любом не будет проблемы.
← →
oxffff © (2008-06-28 21:15) [8]
> На любом не будет проблемы.
Увы это не так.
← →
Игорь Шевченко © (2008-06-28 21:43) [9]
> Причем заметил что чаще всего это просиходит на многоядерном
> проце и редко на одноядерном.
да, это верно. Любые ошибки в многопоточном приложении гораздо быстрее проявляются на многоядерных(многопроцессорных) конфигурациях, чем с одним процессором.
Зато на этих конфигурациях легче отлаживаться.
← →
LonelyWolf (2008-07-01 09:23) [10]Спасибо всем ответившим.
Когда написал тут вопрос, полазил еще по сайту и нашел линк на книгу Рихтера. Там понравилось как разжевано про Mutex"ы и прочую лабуду. Увидел заодно упоминание Interlocked функций.
Применил их для изменения спорной переменной. Глюк пропал. На многоядерном проце тоже. Сколько ни мучал прогу, так глюк и не выскочил.
Изменил и все остальные изменения в нити глобальных переменных на IntrelockedExchange/InterlockedExchangeAdd... пока полет нормальный.
ЗЫ:
> либо считывание тоже надо в критическую секцию обертывать(а
> иначе она вообще смысла не имеет)
А вот об этом нигде написано не было (или я не заметил). Из доков я понял что в Critical надо оборачивать только изменение переменной, но не ее считывание. Почитав Рихтера понял что надо и там и там...
← →
Loginov Dmitry © (2008-07-02 00:52) [11]> Из доков я понял что в Critical надо оборачивать только
> изменение переменной, но не ее считывание. Почитав Рихтера
> понял что надо и там и там...
Имхо, от задачи зависит. Если переменная - ссылка на какой-нибудь глобальный TList, то работу со списком нужно обязательно заворачивать в критическую секцию. Для простых переменных, имхо, это следует делать только при необходимости.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2009.09.13;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.005 c