In message <200006142243.HAA20586 / hanare00.math.sci.hokudai.ac.jp>
gotoken / math.sci.hokudai.ac.jp writes:

> >  Thread.start do
> >    $m.synchronize do                # (1)ここでデッドロック?
> >#1    $m.lock                        # #1を外し(1)コメントアウトするとOK
> >      s = ns
> >    end
(略)
> ので,ブロック内で Mutex#lock を呼ぶと当然deadlockになります.

# そりゃそうですけど.

いや,そうじゃなくて,

    $m.synchronize do
      s = ns
    end

だとデッドロックした様子で,

    $m.lock
    s = ns
    $m.unlock

だと動くようだ,っていう話だと思いますよ.


理由は「あるブロックで導入されたローカル変数はそのブロック内でのみ有効
になる」からです.子スレッドの方は何もいわずに例外で終了してしまってる
んです.

# Thread.abort_on_exception = true って頭の方に加えて実行してみると,
# "undefined local variable `s'" っていってちゃんと全体が落ちます :-)
# つい最近おんなじようなことしてはまってたのは秘密 :-)

つまり Mutex#synchronize のブロックの外では s が定義されてないんです.
lock/unlock を使った場合にはブロックを導入してないので大丈夫.
synchronize を使いたいならその前に `s = nil' とかいれといたら良いでしょ
う.


ちなみにこの例の場合,上記のブロック内で新たに導入されたローカル変数は
ブロックローカル,というルールにより,s はスレッドローカルになります.
だからそもそもここで相互排除を行う必要は無かったりして.

# ....ですよね? 親スレッドが accept したせいで ns のアクセスが競合するっ
# ていう事は無かったですよね?

さらに下の gets して write,っていう動作の方でも,s にアクセスできるの
は s をもってるスレッドだけなので,やっぱり相互排除はいりません.


-- 
柳川和久 @ 東大阪市 . 大阪府                                  June 15, 2000
「田園の,日差しの農場?」「ふざけるにゃ!」