Feature #3251: allow to unlock mutex locked by another thread
http://redmine.ruby-lang.org/issues/show/3251

起票者: Yusuke Endoh
ステータス: Open, 優先度: Normal
担当者: Koichi Sasada, カテゴリ: core, Target version: 1.9.x

遠藤です。

現状では mutex は lock したスレッドからしか unlock できませんが、
これを許可するようにしませんか。動機は 2 つあります。

1) Python の condition variable が mutex を別スレッドから unlock
   することで実装されている、のが真似できる
2) Thread#raise を race condition なしに使えるようになる (気がする)


1 について、Python の condition variable は以下のような感じに実装
されています。

  def wait(m1)
    m2 = Mutex.new
    m2.lock
    @waiters << m2
    m1.unlock
    begin
      m2.lock
    ensure
      m1.lock
    end
  end

  def signal
    @waiters.shift.unlock
  end

つまり、wait は二重に mutex を lock しようとすることでブロックし、
signal は mutex を別スレッドから unlock することでブロックしている
スレッドを再開します。
今の ConditionVariable の実装には大量の問題点が指摘されているので、
Python の真似をするとよいのではと思います。

# 権威主義


2 について、現状は Thread#raise には以下のような race が存在します。

  t1: begin 節を実行している
  t2: t1.raise する
  t1: rescue/ensure 節の実行を開始する
  t3: t1.raise する
  t1: rescue/ensure 節が実行されないまま再度例外が発生する

# ちなみにこの race はシグナルにも存在します

これを、Thread#raise の前に Mutex#lock するというルールにすれば、
race を避けて使うことができるようになります。と思います。

  t1: begin 節を実行している
  t2: m.lock; t1.raise する
  t1: rescue/ensure 節の実行を開始する
  t3: m.lock が止まらないので t1.raise できない
  t1: 次の例外が投げ込まれる準備ができたら m.unlock する
  t3: m.lock が終わって t1.raise する

-- 
Yusuke Endoh <mame / tsg.ne.jp>


----------------------------------------
http://redmine.ruby-lang.org