Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-1214989005
dreamse
2008-07-02 12:56
2009.09.13
Вопрос по работе потока (Thead)


2-1247038910
petr
2009-07-08 11:41
2009.09.13
Запись в реестр


3-1227089155
Sesh
2008-11-19 13:05
2009.09.13
OracleLob сохранить в текстовый файл


1-1214404357
Jolik
2008-06-25 18:32
2009.09.13
Терятся ссылка на items[0] в TreeView...


2-1246981519
sdc-alex
2009-07-07 19:45
2009.09.13
Обработка БД Access 2000





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский