Книга: Программирование на языке Ruby

13.1.2. Доступ к локальным переменным потока

13.1.2. Доступ к локальным переменным потока

Мы знаем об опасности доступа из потока к переменным, определенным вне его области видимости, но мы также знаем, что у потока могут быть локальные данные. А что делать, если поток хочет «обнародовать» часть принадлежащих ему данных?

Для этой цели предусмотрен специальный механизм. Если объект Thread рассматривать как хэш, то к локальным данным потока можно обратиться из любого места в области видимости этого объекта. Мы не хотим сказать, что так можно обратиться к настоящим локальным переменным; это допустимо лишь для доступа к именованным данным, своим для каждого потока.

Существует также метод key?, который сообщает, используется ли указанное имя в данном потоке.

Внутри потока к таким данным тоже следует обращаться, как к хэшу. Метод Thread.current позволяет сделать запись чуть менее громоздкой.

thread = Thread.new do
t = Thread.current
t[:var1] = "Это строка"
t[:var2] = 365
end
# Доступ к локальным данным потока извне...
x = thread[:var1]              # "Это строка"
y = thread[:var2]              # 365
has_var2 = thread.key?("var2") # true
has_var3 = thread.key?("var3") # false

Отметим, что эти данные доступны другим потокам даже после того, их владелец завершил работу (как в данном случае).

Помимо символа (см. выше), для идентификации локальной переменной потока можно употреблять и строки.

thread = Thread.new do
t = Thread.current
t["var3"] = 25
t[:var4] = "foobar"
end
a = thread[:var3] = 25
b = thread["var4"] = "foobar"

He путайте эти специальные имена с настоящими локальными переменными. В следующем фрагменте разница видна более отчетливо:

thread = Thread.new do
 t = Thread.current
 t["var3"] = 25
 t[:var4] = "foobar"
 var3 = 99         # Настоящие локальные переменные
 var4 = "zorch"    # (извне недоступны)
end
a = thread[:var3]  # 25
b = thread["var4"] # "foobar"

И еще отметим, что ссылку на объект (на настоящую локальную переменную) внутри потока можно использовать для сокращенной записи. Это справедливо, если вы сохраняете одну и ту же ссылку, а не создаете новую.

thread = Thread.new do
 t = Thread.current
 x = "nXxeQPdMdxiBAxh"
 t[:my_message] = x
 x.reverse!
 x.delete! "x"
 x.gsub!(/[A-Z]/,"")
 # С другой стороны, присваивание создает новый объект,
 # поэтому "сокращение" становится бесполезным...
end
а = thread[:my_message] # "hidden"

Ясно, что сокращение не будет работать и в том случае, когда вы имеете дело с объектами наподобие Fixnum, которые хранятся как непосредственные значения, а не ссылки.

Оглавление книги


Генерация: 1.682. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз