Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
endthreads = []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 #... endendНо нечто подобное может произойти в сложной программе (или при рекурсивном вызове метода). Какова бы ни была причина, последствием будет тупиковая ситуация. Уход от нее — одно из достоинств модуля-примеси
Monitor@mutex = Mutex.newdef some_method @mutex.synchronize do #... some_other_method # Тупиковая ситуация! endenddef some_other_method @mutex.synchronize do #... endendМодуль-примесь
Monitornew_condКласс
ConditionVariablemonitor.rbthreadwait_untilwait_whilewaittimeoutnilПоскольку примеры работы с потоками у нас кончаются, то в листинге 13.5 мы предлагаем реализацию классов
QueueSizedQueue# Автор: Shugo Maedarequire '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 endendclass 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 @full_cond.broadcast end endendЕще один вариант синхронизации (двузначную блокировку со счетчиком) предлагает библиотека
sync.rbSync_mincludeextendMutex_mlocked?shared?exclusive?lockunlocktry_lock
