Потокобезопасность

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Потокобезопасность

Сообщение Brainenjii » 14.07.2010 12:03:39

Здравствуйте,

Последнее время довольно много приходится работать с потоками. И привычный Synchronize начинает раздражать. Поискав в инете нашёл TCriticalSection - показалось, что вот решение проблем. Обычно делаю так:
Код: Выделить всё
  With TCriticalSection.Create Do
    Begin
      Enter;
      //Do some action
      Leave;
      Free;
    End;

Какова применимость такого подхода?
  1. Подойдёт ли он для, скажем, записи в лог-файл, или WriteLn?
  2. Можно ли таким образом обрабатывать большые списки с которыми работают остальные потоки, с кучей обращений к БД и времени исполнения в несколько секунд?
  3. Обращаться в основной поток, например для того же изменения гуя, что часто приводят в пример для Synchronize?

Спасибо
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Потокобезопасность

Сообщение FedeX » 14.07.2010 12:14:31

TCriticalSection имеет смысл, только если все остальные потоки обращаясь к тем же ресурсам тоже обрамляют обращение к ним в критические секции.
Аватара пользователя
FedeX
постоялец
 
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Re: Потокобезопасность

Сообщение stikriz » 14.07.2010 12:16:19

Критическая секция должна существовать все время, пока существует разделяемый объект. Создать её и тут же грохнуть? А если парараллельно кто-то еще хочет обратится к разделяемому объекту, то он свою критическую секцию создаст? :-) Себе родному?
Смысл в том, чтобы у одной и той же критической секции из разных потоков просить доступ к объекту, который в общем пользовании.
Насчет окошек, то синхронизе - лучший вариант. Можно, конечно конву блокировать, но это отдельная песня для программ, которые рисуют на канве, а не вообще для интерфейсных элементов.
Аватара пользователя
stikriz
энтузиаст
 
Сообщения: 612
Зарегистрирован: 15.03.2006 09:37:47

Re: Потокобезопасность

Сообщение Bupyc » 14.07.2010 12:40:07

Вот такой код

Код: Выделить всё
  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;
Bupyc
постоялец
 
Сообщения: 137
Зарегистрирован: 29.08.2007 18:22:42

Re: Потокобезопасность

Сообщение Brainenjii » 14.07.2010 12:55:09

Ясненько, спасибо. Значит ошибки пошли все-таки из-за неправильного применения секций.

Добавлено спустя 51 минуту 27 секунд:
И ещё вопрос - стала довольно рандомно выпадать ошибка:
Access violation
Marked memory at $02E82CB8 invalid
Wrong signature $AAAAAAAA instead of B67DCE51

цифры, разумеется, варьируются. Из-за чего это может произойти - никогда не встречал подобного
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Потокобезопасность

Сообщение Timid » 14.07.2010 18:36:34

Что ж тут неясного, доступ запрещен. А остальное - это можете только вы сами в дебагере отыскать.

Скорее всего, Вы просто не понимаете принцип использования критических секций.
Есть очень хорошая статья на "Королевстве", почитайте.

Но если коротко, то критическая секция формируется через обращение к ячейке, для которой операция "проверка значения и запись при нулевом значении" будет атомарна - то есть неразделима в многопроцессной среде.
Фактически, это как железнодорожная стрелка - все подошли с разных сторон, если стрелка свободна, то дергают к себе. Кто-то был первым, стрелка включается к нему. Он свободно "входит в секцию" и делает свои дела. Когда выходит - стрелка освобождается. Кто-то другой может включить на себя.
Пока стрелка занята, все подошедшие регулярно дергают рычаг стрелки на себя и ждут.

Проблема в том, что фактически такое включение - две операции - проверка состояния флага и его установка. Если атомарности не будет, то два процесса могут проверить флаг, а затем его установить одновременно. И войти в критическую секцию вместе. А сам код внутри критической секции будет, скорее всего, очень критичен к "однопоточности".

Прочитайте статью на "Королевстве Дельфи" и постройте для себя схему работы Ваших потоков - наверное где-то у Вас есть лишний выход из секции или ее удаление из памяти без освобождения, либо вход в секцию без создания...
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 18

Рейтинг@Mail.ru