共享互斥量的交替例程 [英] Alternating routines sharing a mutex
问题描述
我有方法a
,该方法在某个随机时间重复调用,从而触发方法b
,该方法在某个随机时间之后完全执行,并且在它自己的线程中.我想确保a
的后续执行一直等到b
完成,这由a
的当前执行触发.换句话说,a
和b
要交替执行.我尝试使用互斥量和条件变量来执行此操作,如下所示:
def a
Thread.new do
$mutex.synchronize do
puts "a"
b
$cv.wait($mutex)
end
end
end
def b
Thread.new do
sleep(rand)
$mutex.synchronize do
puts "b"
$cv.signal
end
end
end
$mutex, $cv = Mutex.new, ConditionVariable.new
loop{a; sleep(rand)}
在此代码中,方法a
中的$mutex.synchronize do ... end
确保在$cv.wait($mutex)
将$cv
设置为信号侦听模式之前,不会调用方法b
中的$cv.signal
(也在另一个$mutex.synchronize do ... end
中). 文档中给出了很多. /p>
我打算在方法a
中分配给$mutex.synchronize do ... end
的另一个功能是避免方法a
的连续执行.我的理由是,方法a
中的$cv.wait($mutex)
应该避免在调用方法b
中的$cv.signal
之前应完成并释放$mutex
.
我希望交替执行a
和b
,从而交替打印"a"
和"b"
.但实际上,事实并非如此. "a"
或"b"
中的每一个都可以连续打印.
此后,我认为,即使$cv
(或$mutex
)处于等待模式,一旦$cv.wait($mutex)
已称为.所以我在a
中添加了一些虚拟进程,将其更改为:
def a
Thread.new do
$mutex.synchronize do
puts "a"
b
$cv.wait($mutex)
nil # Dummy process intended to keep `$mutex` locked until `$cv` is released
end
end
end
但是没有效果.
如何解决?或者,我对此有何误解?
我知道这听起来很奇怪,但是使用队列来阻塞那些线程会更容易:
def a
Thread.new do
$queue.pop
puts "a"
b
end
end
def b
Thread.new do
sleep(rand)
puts "b"
$queue << true
end
end
$queue = Queue.new
$queue << true
loop{a; sleep(rand)}
I have method a
that is invoked repeatedly at some random time, which triggers method b
, which is completely executed after some random time and is in it own thread. I want to ensure that a subsequent execution of a
waits until b
is completed, which is triggered by the current execution of a
. In other words, a
and b
are to be executed alternatively. I tried to do this using mutex and condition variable as follows:
def a
Thread.new do
$mutex.synchronize do
puts "a"
b
$cv.wait($mutex)
end
end
end
def b
Thread.new do
sleep(rand)
$mutex.synchronize do
puts "b"
$cv.signal
end
end
end
$mutex, $cv = Mutex.new, ConditionVariable.new
loop{a; sleep(rand)}
In this code, $mutex.synchronize do ... end
in method a
ensures that $cv.signal
(also within another $mutex.synchronize do ... end
) in method b
is not invoked until $cv.wait($mutex)
sets $cv
into listening mode for signals. This much is given in the document.
Another function I intended to assign to $mutex.synchronize do ... end
in method a
is to avoid consecutive execution of method a
. My reasoning is that $cv.wait($mutex)
in method a
should avoid $mutex
from being completed and released until $cv.signal
in method b
is invoked, by which time b
should be finished.
I expected that a
and b
are executed alternatively, thereby printing "a"
and "b"
alternatively. But in reality, they are not; each of "a"
or "b"
can be printed consecutively.
After that, I thought that my reasoning above may be wrong in the sense that $mutex
is rather completed and released even if $cv
(or $mutex
) is in waiting mode, once $cv.wait($mutex)
has been called. So I added some dummy process to a
, changing it to:
def a
Thread.new do
$mutex.synchronize do
puts "a"
b
$cv.wait($mutex)
nil # Dummy process intended to keep `$mutex` locked until `$cv` is released
end
end
end
but that did not have effect.
How can this be fixed? Or, what am I wrong about this?
I know it sounds strange, but it will be easier to use a queue to block those threads:
def a
Thread.new do
$queue.pop
puts "a"
b
end
end
def b
Thread.new do
sleep(rand)
puts "b"
$queue << true
end
end
$queue = Queue.new
$queue << true
loop{a; sleep(rand)}
这篇关于共享互斥量的交替例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!