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

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

Жанры

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

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

Экспансия

Каменев Алекс
8. Цитадели гордыни
Фантастика:
героическая фантастика
боевая фантастика
5.00
рейтинг книги
Экспансия

Дважды одарённый. Том IX

Тарс Элиан
9. Дважды одаренный
Фантастика:
альтернативная история
аниме
фэнтези
попаданцы
5.57
рейтинг книги
Дважды одарённый. Том IX

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Черный Кровавый Триллиум

Нортон Андрэ
Шедевры фантастики
Фантастика:
фэнтези
4.75
рейтинг книги
Черный Кровавый Триллиум

Маленькая женщина Большого

Зайцева Мария
5. Наша
Любовные романы:
эро литература
современные любовные романы
5.71
рейтинг книги
Маленькая женщина Большого

Ловец мелкого жемчуга

Берсенева Анна
4. Гриневы. Капитанские дети
Любовные романы:
современные любовные романы
8.90
рейтинг книги
Ловец мелкого жемчуга

Прайм. Рунный призрак

Бор Жорж
3. Легенда
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Прайм. Рунный призрак

Принц-консорт

Дравин Игорь
8. Чужак
Фантастика:
фэнтези
попаданцы
9.15
рейтинг книги
Принц-консорт

Потерянный разум

Кара-Мурза Сергей Георгиевич
Научно-образовательная:
политика
5.00
рейтинг книги
Потерянный разум

Маскарад

Колодан Дмитрий Геннадьевич
1. Зеркала
Фантастика:
детективная фантастика
5.38
рейтинг книги
Маскарад

Статьи разных лет

Вацуро Вадим Эразмович
3. Вацуро В.Э. Избранные труды
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Статьи разных лет

Гражданская война 1918-1921 гг. — урок для XXI века

Кара-Мурза Сергей Георгиевич
Научно-образовательная:
политика
5.00
рейтинг книги
Гражданская война 1918-1921 гг. — урок для XXI века

Дневник

Гомбрович Витольд
Проза:
современная проза
5.00
рейтинг книги
Дневник

Том 3. Советский и дореволюционный театр

Луначарский Анатолий Васильевич
3. Собрание сочинений в восьми томах
Документальная литература:
критика
5.00
рейтинг книги
Том 3. Советский и дореволюционный театр