Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.09.13;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.016 c
4-1217505298
demon
2008-07-31 15:54
2009.09.13
API и WM_MOUSEMOVE


15-1247320167
TIF
2009-07-11 17:49
2009.09.13
Windows 98


2-1247156058
liveD
2009-07-09 20:14
2009.09.13
невизуальные компоненты


15-1247622069
DV-Karpov
2009-07-15 05:41
2009.09.13
Кнопки в системном меню (Стиль Windows XP)


15-1247255297
Shyrick
2009-07-10 23:48
2009.09.13
Сложение чисел в двоичной системе