Чтение онлайн

на главную - закладки

Жанры

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

Не все в Ruby безопасно относительно потоков, но имеются методы синхронизации, которые позволяют контролировать доступ к переменным и ресурсам, защищать критические секции программы и избегать тупиковых ситуаций. Мы рассмотрим их в этой главе и проиллюстрируем на примерах.

13.1. Создание потоков и манипулирование ими

К числу основных операций над потоками относятся создание потока, передача ему входной информации и получение результатов, останов потока и т.д. Можно получить список запущенных потоков, опросить состояние потока и выполнить

ряд других проверок.

Ниже представлен обзор основных операций.

13.1.1. Создание потоков

Создать поток просто: достаточно вызвать метод new и присоединить блок, который будет исполняться в потоке.

thread = Thread.new do

 # Предложения, исполняемые в потоке...

end

Возвращаемое значение — объект типа

Thread
. Главный поток программы может использовать его для управления вновь созданным потоком.

А если нужно передать потоку параметры? Достаточно передать их методу

Thread.new
, который, в свою очередь, передаст их блоку.

a = 4

b = 5

с = 6

thread2 = Thread.new(а,b,с) do |a, x, y|

 # Манипуляции с a, x и y.

end

# Если переменная а будет изменена новым потоком,

# то главный поток не получит об этом никакого уведомления.

Параметры блока, являющиеся ссылками на существующие переменные, практически неотличимы от самих переменных. Поэтому, например, переменная

а
в каком-то смысле «опасна», что и отражено в комментарии.

Поток может также обращаться к переменным из той же области видимости, в которой был создан. Ясно, что без синхронизации это может стать источником проблем. Главный и любой другой поток могут изменять такую переменную независимо друг от друга, и результаты подобных действий непредсказуемы.

x = 1

y = 2

thread3 = Thread.new do

 # Этот поток может манипулировать переменными x and y

 # из внешней области видимости, но это не всегда безопасно.

 sleep(rand(0)) # Спать в течение случайно выбранного времени

 # (меньше секунды).

 x = 3

end

sleep(rand(0))

puts x

# Если запустить эту программу несколько раз подряд, то может быть

# напечатано как 1, так и 3!

У метода

new
есть синоним
fork
— это имя выбрано по аналогии с хорошо известным системным вызовом в UNIX.

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"

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

Поделиться:
Популярные книги

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

Кодекс Охотника. Книга XII

Винокуров Юрий
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XII

Первый среди равных

Бор Жорж
1. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных

Хозяин Теней 7

Петров Максим Николаевич
7. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 7

Я – Легенда 2: геном хищника

Гарцевич Евгений Александрович
2. Я - Легенда!
Фантастика:
боевая фантастика
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Я – Легенда 2: геном хищника

Двойник короля 12

Скабер Артемий
12. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 12

Рубежник

Билик Дмитрий Александрович
1. Бедовый
Фантастика:
юмористическая фантастика
городское фэнтези
мистика
5.00
рейтинг книги
Рубежник

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Курсант: назад в СССР

Дамиров Рафаэль
1. Курсант
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Курсант: назад в СССР

Ключи мира

Кас Маркус
9. Артефактор
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Ключи мира

На границе империй. Том 7

INDIGO
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
На границе империй. Том 7

Сталин

Рыбас Святослав Юрьевич
1190. Жизнь замечательных людей
Документальная литература:
биографии и мемуары
4.50
рейтинг книги
Сталин

Петля, Кадетский корпус. Книга вторая

Алексеев Евгений Артемович
2. Петля
Фантастика:
боевая фантастика
попаданцы
аниме
4.80
рейтинг книги
Петля, Кадетский корпус. Книга вторая