Координация потоков
При работе с потоками, на этапе первоначального знакомства с ними, неизбежны ошибки. Особенно неприятны ошибки, связанные с конфликтами потоков, обращающихся к разделяемым ресурсам, а также глобальным переменным. Иногда бывает необходимо, чтобы потоки работали слаженно, т. е., например, после выполнения какого-либо события в одном потоке вам необходимо, чтобы возникало определенное постоянное событие в другом потоке. Все это можно объединить под общим названием координации потоков. Рассмотрим, как можно эффективно управлять потоками для достижения решения практических задач.
Для начала определим, какие способы хранения локальных переменных потока нам предоставляет Delphi. Таких способов три:
- хранение локальных переменных в стеке потока. Так как любой поток приложения получает свой собственный стек, то он будет иметь собственные локальные переменные;
- сохранение локальных переменных в объекте потомка класса TThread;
- хранение локальных переменных на уровне операционной системы, используя в описании локальных переменных слово threadvar.
Первый способ является самым простым и очевидным, а также и самым эффективным. Доступ к локальным переменным, расположенным в стеке потока, самый быстрый.
Рассмотрим два других способа хранения локальных переменных потока. Второй способ проще и эффективнее, чем третий. Рассмотрим его на примере:
type
TMyThreadl = class(TThread)
private
i,j,k,1: integer; // локальные переменные потока типа integer
a,b,c: char; // локальные переменные потока типа char
end;
Эффективность объявления локальных переменных в потомке класса TThread очевидна, т. к. доступ к любому полю объекта осуществляется очень быстро (примерно в 10-11 раз быстрее, чем при использовании описания
threadvar).
Третий способ хранения локальных переменных (с помощью threadvar), служит для создания в потоках локальных копий глобальных переменных. Глобальные переменные могут использоваться всеми потоками приложения, при этом может возникнуть ситуация, когда при изменении глобальной переменной одним потоком происходит изменение этой же глобальной пере
менной другим потоком. В результате значение, установленное первым потоком, бесследно исчезает, приводя к нежелательным последствиям (в данном примере произойдет обработка ошибочного значения глобальной переменной первым потоком). Для исключения такой ситуации Win32 API предлагает средство хранения локальных данных потоков (thread-local storage). С помощью этого средства можно создавать локальные копии глобальных переменных для любого потока. При этом требуется всего лишь заменить одно слово var при объявлении глобальных переменных на слово threadvar.