модуль MonitorMixin
В конкурентном программировании монитор — это объект или модуль, предназначенный для безопасного использования более чем одной нитью. Определяющей характеристикой монитора является то, что его методы выполняются с взаимным исключением. То есть в любой момент времени не более одной нити может выполнять любой из его методов. Это взаимное исключение значительно упрощает рассуждения о реализации мониторов по сравнению с рассуждениями о параллельном коде, обновляющем структуру данных.
Дополнительную информацию о общих принципах можно найти на странице Википедии для Мониторов.
Примеры
Простой object.extend
require 'monitor.rb'
buf = []
buf.extend(MonitorMixin)
empty_cond = buf.new_cond
# consumer
Thread.start do
loop do
buf.synchronize do
empty_cond.wait_while { buf.empty? }
print buf.shift
end
end
end
# producer
while line = ARGF.gets
buf.synchronize do
buf.push(line)
empty_cond.signal
end
end
Поток-потребитель ожидает, пока поток-производитель не запишет строку в буфер, в то время как buf.empty?. Поток-производитель (главный поток) считывает строку из ARGF и записывает её в буфер, затем вызывает empty_cond.signal для уведомления потока-потребителя о новых данных.
Простой Class include
require 'monitor'
class SynchronizedArray < Array
include MonitorMixin
def initialize(*args)
super(*args)
end
alias :old_shift :shift
alias :old_unshift :unshift
def shift(n=1)
self.synchronize do
self.old_shift(n)
end
end
def unshift(item)
self.synchronize do
self.old_unshift(item)
end
end
# other methods ...
end
SynchronizedArray реализует Array с синхронизированным доступом к элементам. Этот Class реализован как подкласс Array, который включает модуль MonitorMixin.
Методы публичного класса
Исходный код
# File ext/monitor/lib/monitor.rb, line 222 def initialize(...) super mon_initialize end
Используйте extend MonitorMixin или include MonitorMixin вместо этого конструктора. Обратитесь к примерам выше, чтобы понять, как использовать этот модуль.
Публичные методы экземпляра
Исходный код
# File ext/monitor/lib/monitor.rb, line 169 def mon_enter @mon_data.enter end
Вход в секцию исключительного доступа.
Исходный код
# File ext/monitor/lib/monitor.rb, line 176 def mon_exit mon_check_owner @mon_data.exit end
Выход из секции исключительного доступа.
Исходный код
# File ext/monitor/lib/monitor.rb, line 184 def mon_locked? @mon_data.mon_locked? end
Возвращает true, если этот монитор заблокирован какой-либо нитью
Исходный код
# File ext/monitor/lib/monitor.rb, line 191 def mon_owned? @mon_data.mon_owned? end
Возвращает true, если этот монитор заблокирован текущей нитью.
Исходный код
# File ext/monitor/lib/monitor.rb, line 200 def mon_synchronize(&b) @mon_data.synchronize(&b) end
Входит в секцию исключительного доступа и выполняет блок. Выходит из секции исключительного доступа автоматически при выходе из блока. См. пример в MonitorMixin.
Исходный код
# File ext/monitor/lib/monitor.rb, line 160 def mon_try_enter @mon_data.try_enter end
Попытка входа в секцию исключительного доступа. Возвращает false в случае неудачи.
Исходный код
# File ext/monitor/lib/monitor.rb, line 209
def new_cond
unless defined?(@mon_data)
mon_initialize
@mon_initialized_by_new_cond = true
end
return ConditionVariable.new(@mon_data)
end Создаёт новый MonitorMixin::ConditionVariable, связанный с объектом Monitor.
Приватные методы экземпляра
Исходный код
# File ext/monitor/lib/monitor.rb, line 243 def mon_check_owner @mon_data.mon_check_owner end
Обеспечивает, что MonitorMixin принадлежит текущей нити, в противном случае генерирует исключение.
Исходный код
# File ext/monitor/lib/monitor.rb, line 229
def mon_initialize
if defined?(@mon_data)
if defined?(@mon_initialized_by_new_cond)
return # already initialized.
elsif @mon_data_owner_object_id == self.object_id
raise ThreadError, "already initialized"
end
end
@mon_data = ::Monitor.new
@mon_data_owner_object_id = self.object_id
end Инициализирует MonitorMixin после включения в класс или когда объект был расширен с помощью MonitorMixin
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.