Ruby 2.4

MonitorMixin

module MonitorMixin

在并发编程中,监视器是多个线程安全使用的对象或模块。监视器的定义特征是它的方法在互斥的情况下执行。也就是说,在每个时间点,最多一个线程可能正在执行其任何方法。与推断更新数据结构的并行代码相比,这种互斥极大地简化了关于监视器实现的推理。

您可以阅读关于监视器维基百科页面上的一般原理的更多信息

例子

Simple 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 buf.empty?。生产者线程(主线程)从ARGF读取一行并将其推入buf,然后调用empty_cond.signal以通知消费者线程新数据。

简单类包括

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实现具有对项目的同步访问权限的数组。该类是作为包含MonitorMixin模块的Array的子​​类实现的。

公共类方法

extend_object(obj) Show source

调用超类方法

# File lib/monitor.rb, line 159 def self.extend_object(obj) super(obj) obj.__send__(:mon_initialize) end

new(*args) Show source

使用extend MonitorMixininclude MonitorMixin代替这个构造函数。看看上面的例子来理解如何使用这个模块。

调用超类方法

# File lib/monitor.rb, line 233 def initialize(*args) super mon_initialize end

公共实例方法

mon_enter() Show source

进入专属部分。

# File lib/monitor.rb, line 184 def mon_enter if @mon_owner != Thread.current @mon_mutex.lock @mon_owner = Thread.current @mon_count = 0 end @mon_count += 1 end

mon_exit() Show source

留下专属部分。

# File lib/monitor.rb, line 196 def mon_exit mon_check_owner @mon_count -=1 if @mon_count == 0 @mon_owner = nil @mon_mutex.unlock end end

mon_synchronize() { || ... } Show source

进入独占部分并执行该块。块停止时自动保留专用段。见下例MonitorMixin

# File lib/monitor.rb, line 210 def mon_synchronize mon_enter begin yield ensure mon_exit end end

Also aliased as: synchronize

mon_try_enter() Show source

尝试输入专属部分。false锁定失败时返回。

# File lib/monitor.rb, line 167 def mon_try_enter if @mon_owner != Thread.current unless @mon_mutex.try_lock return false end @mon_owner = Thread.current @mon_count = 0 end @mon_count += 1 return true end

Also aliased as: try_mon_enter

new_cond() Show source

Creates a new MonitorMixin::ConditionVariable associated with the receiver.

# File lib/monitor.rb, line 224 def new_cond return ConditionVariable.new(self) end

synchronize()

Alias for: mon_synchronize

try_mon_enter()

For backward compatibility

Alias for: mon_try_enter

私有实例方法

mon_check_owner() Show source

# File lib/monitor.rb, line 246 def mon_check_owner if @mon_owner != Thread.current raise ThreadError, "current thread not owner" end end

mon_enter_for_cond(count) Show source

# File lib/monitor.rb, line 252 def mon_enter_for_cond(count) @mon_owner = Thread.current @mon_count = count end

mon_exit_for_cond() Show source

# File lib/monitor.rb, line 257 def mon_exit_for_cond count = @mon_count @mon_owner = nil @mon_count = 0 return count end

mon_initialize() Show source

在包含在类中或 MonitorMixin 扩展了对象后初始化MonitorMixin

# File lib/monitor.rb, line 240 def mon_initialize @mon_owner = nil @mon_count = 0 @mon_mutex = Thread::Mutex.new end