共享互斥量的交替例程 [英] Alternating routines sharing a mutex

查看:101
本文介绍了共享互斥量的交替例程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有方法a,该方法在某个随机时间重复调用,从而触发方法b,该方法在某个随机时间之后完全执行,并且在它自己的线程中.我想确保a的后续执行一直等到b完成,这由a的当前执行触发.换句话说,ab要交替执行.我尝试使用互斥量和条件变量来执行此操作,如下所示:

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.

我希望交替执行ab,从而交替打印"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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆