Программирование на языке Ruby
Шрифт:
sleep rand(0)
puts "#{n}: (...играет...)"
sleep rand(0)
puts "#{n}: Я закончил."
@music.synchronize do
@violins_free += 1
@violin.signal if @violins_free == 1
@bows_free += 1
@bow.signal if @bows_free == 1
end
end
end
threads = []
3.times {|i| threads << Thread.new { musician(i) } }
threads.each {|t| t.join }
Мы
13.2.5. Другие способы синхронизации
Еще один механизм синхронизации - это монитор, который в Ruby реализован в библиотеке
monitor.rb
. Это более развитый по сравнению с мьютексом механизм, основное отличие состоит в том, что захваты одного и того же мьютекса не могут быть вложенными, а монитора — могут. Тривиальный случай возникновения такой ситуации вряд ли возможен. В самом деле, кто станет писать такой код:
@mutex = Mutex.new
@mutex.synchronize do
@mutex.synchronize do
#...
end
end
Но нечто подобное может произойти в сложной программе (или при рекурсивном вызове метода). Какова бы ни была причина, последствием будет тупиковая ситуация. Уход от нее — одно из достоинств модуля-примеси
Monitor
.
@mutex = Mutex.new
def some_method
@mutex.synchronize do
#...
some_other_method # Тупиковая ситуация!
end
end
def some_other_method
@mutex.synchronize do
#...
end
end
Модуль-примесь
Monitor
обычно применяется для расширения объекта. Для создания условной переменной предназначен метод new_cond
. Класс
ConditionVariable
в библиотеке monitor.rb
дополнен по сравнению с определением в библиотеке thread
. У него есть методы wait_until
и wait_while
, которые блокируют поток в ожидании выполнения условия. Кроме того, возможен тайм-аут при ожидании, поскольку у
wait
имеется параметр timeout
, равный количеству секунд (по умолчанию nil
). Поскольку примеры работы с потоками у нас кончаются, то в листинге 13.5 мы предлагаем реализацию классов
Queue
и SizedQueue
с помощью монитора. Код приводится с разрешения автора, Шуго Маэда (Shugo Maeda). Листинг 13.5. Реализация класса Queue с помощью монитора
# Автор: Shugo Maeda
require 'monitor'
class Queue
def initialize
@que = []
@monitor = Monitor.new
@empty_cond = @monitor.new_cond
end
def enq(obj)
@monitor.synchronize do
@que.push(obj)
@empty_cond.signal
end
end
def deq
@monitor.synchronize do
while @que.empty?
@empty_cond.wait
end
return @que.shift
end
end
end
class SizedQueue < Queue
attr :max
def initialize(max)
super
@max = max
@full_cond = @monitor.new_cond
end
def enq(obj)
@monitor.synchronize do
while @que.length >= @max
@full_cond.wait
end
super(obj)
end
end
def deq
@monitor.synchronize do
obj = super
if @que.length < @max
@full_cond.signal
end
return obj
end
end
def max=(max)
@monitor.synchronize do
@max = max
Поделиться:
Популярные книги
Кровь на эполетах
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Московское золото и нежная попа комсомолки. Часть Третья
3. Летчик Леха
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Моров. Том 1 и Том 2
1. Моров
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Искатель 6
6. Валинор
Фантастика:
рпг
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Газлайтер. Том 9
9. История Телепата
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 18
18. Черный маг императора
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Ваантан
10. Другая сторона
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности
1. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я Гордый часть 7
7. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Двойник Короля 7
7. Двойник Короля
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XIX
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Герой
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Особый агент
Спецназ. Группа Антитеррор
Детективы:
боевики
7.00
рейтинг книги
На границе империй. Том 3
3. Фортуна дама переменчивая
Фантастика:
космическая фантастика
5.63