模块 MonitorMixin
在并发编程中,监视器是一个对象或模块,旨在被多个线程安全地使用。监视器的定义特征是其方法以互斥方式执行。也就是说,在任何时间点,最多只有一个线程可以执行其任何方法。与推理更新数据结构的并行代码相比,这种互斥极大地简化了对监视器实现的推理。
您可以在维基百科页面上阅读有关一般原则的更多信息 监视器.
示例¶ ↑
简单对象.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,而 buf.empty?
。生产者线程(主线程)从 ARGF
读取一行并将其推送到 buf,然后调用 empty_cond.signal
通知消费者线程有新数据。
简单 Class
包含¶ ↑
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
模块。
公共类方法
extend_object(obj) 点击切换源代码
调用超类方法
# File ext/monitor/lib/monitor.rb, line 152 def self.extend_object(obj) super(obj) obj.__send__(:mon_initialize) end
new(...) 点击切换源代码
使用 extend MonitorMixin
或 include MonitorMixin
而不是此构造函数。查看上面的示例以了解如何使用此模块。
调用超类方法
# File ext/monitor/lib/monitor.rb, line 222 def initialize(...) super mon_initialize end
公共实例方法
mon_enter() 点击切换源代码
进入独占部分。
# File ext/monitor/lib/monitor.rb, line 169 def mon_enter @mon_data.enter end
mon_exit() 点击切换源代码
离开独占部分。
# File ext/monitor/lib/monitor.rb, line 176 def mon_exit mon_check_owner @mon_data.exit end
mon_locked?() 点击切换源代码
如果此监视器被任何线程锁定,则返回 true
# File ext/monitor/lib/monitor.rb, line 184 def mon_locked? @mon_data.mon_locked? end
mon_owned?() 点击切换源代码
如果此监视器被当前线程锁定,则返回 true。
# File ext/monitor/lib/monitor.rb, line 191 def mon_owned? @mon_data.mon_owned? end
mon_synchronize(&b) 点击切换源代码
进入排他部分并执行代码块。代码块退出时,会自动离开排他部分。请参阅 MonitorMixin
中的示例。
# File ext/monitor/lib/monitor.rb, line 200 def mon_synchronize(&b) @mon_data.synchronize(&b) end
别名:synchronize
mon_try_enter() 点击切换源代码
尝试进入排他部分。如果锁定失败,则返回 false
。
# File ext/monitor/lib/monitor.rb, line 160 def mon_try_enter @mon_data.try_enter end
new_cond() 点击切换源代码
创建一个新的 MonitorMixin::ConditionVariable
,与 Monitor
对象相关联。
# 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
私有实例方法
mon_check_owner() 点击切换源代码
# File ext/monitor/lib/monitor.rb, line 241 def mon_check_owner @mon_data.mon_check_owner end
mon_initialize() 点击切换源代码
在将 MonitorMixin
包含到类中或用 MonitorMixin
扩展对象后初始化 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