Потокобезопасность
				
Добавлено: 
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
				Что ж тут неясного, доступ запрещен. А остальное - это можете только вы сами в дебагере отыскать.
Скорее всего, Вы просто не понимаете принцип использования критических секций.
Есть очень хорошая статья на "Королевстве", почитайте.
Но если коротко, то критическая секция формируется через обращение к ячейке, для которой операция "проверка значения и запись при нулевом значении" будет атомарна - то есть неразделима в многопроцессной среде. 
Фактически, это как железнодорожная стрелка - все подошли с разных сторон, если стрелка свободна, то дергают к себе. Кто-то был первым, стрелка включается к нему. Он свободно "входит в секцию" и делает свои дела. Когда выходит - стрелка освобождается. Кто-то другой может включить на себя.
Пока стрелка занята, все подошедшие регулярно дергают рычаг стрелки на себя и ждут.
Проблема в том, что фактически такое включение - две операции - проверка состояния флага и его установка. Если атомарности не будет, то два процесса могут проверить флаг, а затем его установить одновременно. И войти в критическую секцию вместе. А сам код внутри критической секции будет, скорее всего, очень критичен к "однопоточности".
Прочитайте статью на "Королевстве Дельфи" и постройте для себя схему работы Ваших потоков - наверное где-то у Вас есть лишний выход из секции или ее удаление из памяти без освобождения, либо вход в секцию без создания...