原です。

mutex.rb があるにもかかわらず、現在の thread.rb に入っている CV
のコードを元にして、正常に動作するものに書き直そうと思ったので
すが、、、

-----------------------^ cv1.rb
class ConditionVariable
  def initialize
    @waiters = []
  end
  
  def wait(mutex)
    mutex.unlock
    Thread.critical = true
    @waiters.push(Thread.current)
    Thread.stop
    mutex.lock
  end
  
  def signal
    Thread.critical = true
    t = @waiters.shift
    Thread.critical = false
    t.run if t
  end
    
  def broadcast
    Thread.critical = true
    waiters0 = @waitors.dup
    @waiters.clear
    Thread.critical = false
    for t in waiters0
      t.run
    end
  end
end
-----------------------$ cv1.rb

となりました。少し解説すると、現在の thread.rb では

  def wait(mutex)
    mutex.unlock
    @waiters_mutex.synchronize {
      @waiters.push(Thread.current)
    }
    Thread.stop
    mutex.lock
  end

ですが、これは例えば咳さんの TinyQueue でいえば、Thread.stop の前
に Thread.pass を書いただけで、dead lock したりします。これの理由
は前田さんが [ruby-list:14504] で言っているように stop してないう
ちに run されてしまうからです。で、Thread.critical = true をそれ
以前に書かなければならないわけですが、synchronize にも unlock にも
Thread.critical = false というコードが含まれますから、このままで
は効果がありません。そこで cv1.rb の様になったのです。

ところが、cv1.rb でもやはり wait の mutex.unlock の後に「すき間」
があるので、ここに Thread.pass を書いたりすると dead lock を起こ
したりします。そこで次のように改良します。

-----------------------^ cv2.rb
def Thread.exclusive
  begin
    Thread.critical = true
    r = yield
  ensure
    Thread.critical = false
  end
  r
end

class Mutex
  def exclusive_unlock
    return unless @locked
    Thread.exclusive do
      t = @waiting.shift
      @locked = false
      t.wakeup if t
      yield
    end
    self
  end
end

class ConditionVariable
  def initialize
    @waiters = []
  end
  
  def wait(mutex)
    mutex.exclusive_unlock do
      @waiters.push(Thread.current)
      Thread.stop
    end
    mutex.lock
  end
  
  def signal
    t = @waiters.shift
    t.run if t
  end
    
  def broadcast
    waitors0 = nil
    Thread.exclusive do
      waiters0 = @waitors.dup
      @waiters.clear
    end
    for t in waiters0
      t.run
    end
  end
end
-----------------------$ cv2.rb

これでうまく動くと思います。

#同じ事が monitor.rb でも問題になると思いますが、大丈夫なのかな。

signal の後、条件が変わってしまって、、、という [ruby-list:6735]
以降のスレッドで議論された問題は run を使う限りないと思うのです
がどうでしょうか。