Потокобезопасность
Добавлено:
14.07.2010 12:03:39
Brainenjii
Здравствуйте,
Последнее время довольно много приходится работать с потоками. И привычный Synchronize начинает раздражать. Поискав в инете нашёл TCriticalSection - показалось, что вот решение проблем. Обычно делаю так:
- Код: Выделить всё
With TCriticalSection.Create Do
Begin
Enter;
//Do some action
Leave;
Free;
End;
Какова применимость такого подхода?
- Подойдёт ли он для, скажем, записи в лог-файл, или WriteLn?
- Можно ли таким образом обрабатывать большые списки с которыми работают остальные потоки, с кучей обращений к БД и времени исполнения в несколько секунд?
- Обращаться в основной поток, например для того же изменения гуя, что часто приводят в пример для Synchronize?
Спасибо
Re: Потокобезопасность
Добавлено:
14.07.2010 12:14:31
FedeX
TCriticalSection имеет смысл, только если все остальные потоки обращаясь к тем же ресурсам тоже обрамляют обращение к ним в критические секции.
Re: Потокобезопасность
Добавлено:
14.07.2010 12:16:19
stikriz
Критическая секция должна существовать все время, пока существует разделяемый объект. Создать её и тут же грохнуть? А если парараллельно кто-то еще хочет обратится к разделяемому объекту, то он свою критическую секцию создаст?
Себе родному?
Смысл в том, чтобы у одной и той же критической секции из разных потоков просить доступ к объекту, который в общем пользовании.
Насчет окошек, то синхронизе - лучший вариант. Можно, конечно конву блокировать, но это отдельная песня для программ, которые рисуют на канве, а не вообще для интерфейсных элементов.
Re: Потокобезопасность
Добавлено:
14.07.2010 12:40:07
Bupyc
Вот такой код
- Код: Выделить всё
With TCriticalSection.Create Do
Begin
Enter;
//Do some action
Leave;
Free;
End;
не имеет смысла.
Нужно, что бы все потоки, которые обращаются к разделяемому ресурсу, обращались к одному и тому же экземпляру критической секции. Т.е. где то нужно создать экземпляр
- Код: Выделить всё
sectionInstance := TCriticalSection.Create();
а в потоках обращение к разделяемому ресурсу оформлять следующим образом:
- Код: Выделить всё
With sectionInstance Do
Begin
Enter;
//Do some action
Leave;
End;
Re: Потокобезопасность
Добавлено:
14.07.2010 12:55:09
Brainenjii
Ясненько, спасибо. Значит ошибки пошли все-таки из-за неправильного применения секций.
Добавлено спустя 51 минуту 27 секунд:И ещё вопрос - стала довольно рандомно выпадать ошибка:
Access violation
Marked memory at $02E82CB8 invalid
Wrong signature $AAAAAAAA instead of B67DCE51
цифры, разумеется, варьируются. Из-за чего это может произойти - никогда не встречал подобного
Re: Потокобезопасность
Добавлено:
14.07.2010 18:36:34
Timid
Что ж тут неясного, доступ запрещен. А остальное - это можете только вы сами в дебагере отыскать.
Скорее всего, Вы просто не понимаете принцип использования критических секций.
Есть очень хорошая статья на "Королевстве", почитайте.
Но если коротко, то критическая секция формируется через обращение к ячейке, для которой операция "проверка значения и запись при нулевом значении" будет атомарна - то есть неразделима в многопроцессной среде.
Фактически, это как железнодорожная стрелка - все подошли с разных сторон, если стрелка свободна, то дергают к себе. Кто-то был первым, стрелка включается к нему. Он свободно "входит в секцию" и делает свои дела. Когда выходит - стрелка освобождается. Кто-то другой может включить на себя.
Пока стрелка занята, все подошедшие регулярно дергают рычаг стрелки на себя и ждут.
Проблема в том, что фактически такое включение - две операции - проверка состояния флага и его установка. Если атомарности не будет, то два процесса могут проверить флаг, а затем его установить одновременно. И войти в критическую секцию вместе. А сам код внутри критической секции будет, скорее всего, очень критичен к "однопоточности".
Прочитайте статью на "Королевстве Дельфи" и постройте для себя схему работы Ваших потоков - наверное где-то у Вас есть лишний выход из секции или ее удаление из памяти без освобождения, либо вход в секцию без создания...