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

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

Жанры

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

Thread.abort_on_exception = true

t1 = Thread.new do

 puts "Привет!"

 sleep 2

 raise "some exception"

 puts "Пока!"

end

t2 = Thread.new { sleep 100 }

sleep 2

puts "Конец"

В этом примере флаг

abort_on_exception
установлен в
true
на уровне системы в целом (отменяя подразумеваемое по умолчанию значение). Следовательно, когда в потоке
t1
возникает исключение, завершаются и
t1
, и главный поток. Печатается только слово «Привет!».

В следующем примере эффект такой же:

t1 = Thread.new do

 puts "Привет!"

 sleep 2

 raise "some exception"

 puts "Пока!"

end

t1.abort_on_exception = true

t2 = Thread.new { sleep 100 }

sleep 2

puts "Конец"

А вот в следующем оставлено принимаемое по умолчанию значение

false
, и мы наконец-то видим слово «Конец», печатаемое главным потоком (слова «Пока!» мы не увидим никогда, поскольку поток
t1
при возникновении исключения завершается безусловно).

t1 = Thread.new do

 puts "Привет!"

 sleep 2

 raise "some exception"

 puts "Пока!"

end

t2 = Thread.new { sleep 100 }

sleep 2

puts "Конец"

# Выводится:

Привет!

Конец

13.1.6. Группы потоков

Группа потоков — это механизм управления логически связанными потоками. По умолчанию все потоки принадлежат группе

Default
(это константа класса). Но если создать новую группу, то в нее можно будет помещать потоки.

В любой момент времени поток может принадлежать только одной группе. Если поток помещается в группу, то он автоматически удаляется из той группы, которой принадлежал ранее.

Метод класса

ThreadGroup.new
создает новую группу потоков, а метод экземпляра
add
помещает поток в группу.

f1 = Thread.new("file1") { |file| waitfor(file) }

f2 = Thread.new("file2") { |file| waitfor(file) }

file_threads = ThreadGroup.new

file_threads.add f1

file_threads.add f2

Метод экземпляра

list
возвращает массив всех потоков, принадлежащих данной группе.

# Подсчитать все "живые" потоки в группе this_group.

count = 0

this_group.list.each {|x| count += 1 if x.alive? }

if count < this_group.list.size

 puts "Некоторые потоки в группе this_group уже скончались."

else

 puts "Все потоки в группе this_group живы."

end

В класс

ThreadGroup
можно добавить немало полезных методов. В примере ниже показаны методы для возобновления всех потоков, принадлежащих группе, для группового ожидания потоков (с помощью
join
) и для группового завершения потоков:

class ThreadGroup

def wakeup

 list.each { |t| t.wakeup }

end

def join

 list.each { |t| t.join if t != Thread.current }

end

def kill

 list.each { |t| t.kill }

end

end

13.2. Синхронизация потоков

Почему необходима синхронизация? Потому что из-за «чередования» операций доступ к переменным и другим сущностям может осуществляться в порядке, который не удается установить путем чтения исходного текста отдельных потоков. Два и более потоков, обращающихся к одной и той же переменной, могут взаимодействовать между собой непредвиденными способами, и отлаживать такую программу очень трудно.

Рассмотрим простой пример:

x = 0

t1 = Thread.new do

 1.upto(1000) do

x = x + 1

 end

end

t2 = Thread.new do

 1.upto(1000) do

x = x + 1

 end

end

t1.join

t2.join

puts x

Сначала переменная

x
равна 0. Каждый поток увеличивает ее значение на тысячу раз. Логика подсказывает, что в конце должно быть напечатано 2000.

Но фактический результат противоречит логике. На конкретной машине было напечатано значение 1044. В чем дело?

Мы предполагали, что инкремент целого числа — атомарная (неделимая) операция. Но это не так. Рассмотрим последовательность выполнения приведенной выше программы. Поместим поток

t1
слева, а поток
t2
справа. Каждый квант времени занимает одну строчку и предполагается, что к моменту, когда был сделан этот мгновенный снимок, переменная
x
имела значение 123.

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

Анна Иоановна

Сахаров Андрей Николаевич
9. Романовы. Династия в романах
Проза:
историческая проза
5.60
рейтинг книги
Анна Иоановна

Кентерберийские рассказы

Чосер Джеффри
Старинная литература:
европейская старинная литература
8.00
рейтинг книги
Кентерберийские рассказы

Марш Турецкого

Незнанский Фридрих Евсеевич
Детективы:
крутой детектив
5.50
рейтинг книги
Марш Турецкого

Третий. Том 5

INDIGO
5. Отпуск
Фантастика:
космическая фантастика
фантастика: прочее
5.67
рейтинг книги
Третий. Том 5

Снежная королева

Виндж Джоан
1. Снежная королева
Фантастика:
научная фантастика
8.50
рейтинг книги
Снежная королева

12 историй о любви

Коллектив авторов
Проза:
русская классическая проза
5.00
рейтинг книги
12 историй о любви

Средневековая история. Тетралогия

Гончарова Галина Дмитриевна
Средневековая история
Фантастика:
фэнтези
попаданцы
9.16
рейтинг книги
Средневековая история. Тетралогия

Эпоха Опустошителя. Том I

Павлов Вел
1. Вечное Ристалище
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эпоха Опустошителя. Том I

Ведьмы Плоского мира

Пратчетт Терри Дэвид Джон
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Ведьмы Плоского мира

Том 2. Рассказы и пьесы 1904-1907

Андреев Леонид Николаевич
2. Собрание сочинений в шести томах
Проза:
русская классическая проза
5.00
рейтинг книги
Том 2. Рассказы и пьесы 1904-1907

Метаморфозы власти

Тоффлер Элвин
Научно-образовательная:
философия
6.60
рейтинг книги
Метаморфозы власти

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

Винокуров Юрий
1. Кодекс Охотника
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
боевая фантастика
5.00
рейтинг книги
Кодекс Охотника

100 великих войн

Соколов Борис Вадимович
100 великих
Справочная литература:
энциклопедии
6.40
рейтинг книги
100 великих войн

Тор. Дитя Асгарда

Vegetarianka
Фантастика:
фэнтези
мистика
5.00
рейтинг книги
Тор. Дитя Асгарда