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

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

Жанры

Программирование на языке 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.

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

Электроника?.. Нет ничего проще!

Эймишен Жан-Поль
885. Массовая радиобиблиотека
Техника:
радиоэлектроника
5.00
рейтинг книги
Электроника?.. Нет ничего проще!

Враг из прошлого тысячелетия

Еслер Андрей
4. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.25
рейтинг книги
Враг из прошлого тысячелетия

Резонанс Ци. Том 6

Орлов Андрей Юрьевич
6. Резонанс Ци
Фантастика:
постапокалипсис
рпг
уся
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Резонанс Ци. Том 6

Вторая Фаза

Кораблев Родион
27. Другая сторона
Фантастика:
боевая фантастика
рпг
фантастика: прочее
постапокалипсис
попаданцы
5.00
рейтинг книги
Вторая Фаза

Избранные циклы фантастических романов. Компиляция. Книги 1-20

Amazerak
Избранные циклы фантастических романов
Фантастика:
фэнтези
боевая фантастика
5.00
рейтинг книги
Избранные циклы фантастических романов. Компиляция. Книги 1-20

Возвращение

Кораблев Родион
5. Другая сторона
Фантастика:
боевая фантастика
6.23
рейтинг книги
Возвращение

3ds Max 2008. Секреты мастерства

Верстак Владимир
Компьютеры и Интернет:
программное обеспечение
5.00
рейтинг книги
3ds Max 2008. Секреты мастерства

"Фантастика 2025-112". Компиляция. Книги 1-30

Булгакова Ольга Анатольевна
Фантастика 2025. Компиляция
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Фантастика 2025-112. Компиляция. Книги 1-30

Последний рейд

Сай Ярослав
5. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Последний рейд

Хроника

Саксон Анналист
Mediaevalia: средневековые литературные памятники и источники
Научно-образовательная:
история
5.00
рейтинг книги
Хроника

Константин Коровин вспоминает…

Зильберштейн Илья Самойлович
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Константин Коровин вспоминает…

Контртеррор

Валериев Игорь
6. Ермак
Фантастика:
альтернативная история
5.00
рейтинг книги
Контртеррор

Душехранитель

Гомонов Сергей
Фантастика:
боевая фантастика
ужасы и мистика
5.00
рейтинг книги
Душехранитель

Аргонавты

Дионис Антонио
Старинная литература:
мифы. легенды. эпос
5.00
рейтинг книги
Аргонавты