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 MonitorMixin
或include 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