咳といいます。

> なるほど。多くのライブラリはあんまりスレッドのことを考慮せず
> に書いてあります、かもしれません。スレッド標準装備をうたって
> るんだから、もうちょっとスレッド対応が簡単な方がよいかも。
> Javaのsyncronized構文とか導入した方が良いのかなあ。

どうなんでしょう。
最近 mutex_m.rb を改造して遊んでました。

(1) synchronize 中、そのスレッドは synchronize 可能 な synchronize

(2) synchronize 中でないと例外を発生させる in_synchronize

(3) attr_reader/writer/accessor のようなもので
    同期する synchronize_reader/writer/accessor や
    lockしてないと例外を発生させる lock_reader/writer/accessor

(4) メソッドを alias して同じ名前で synchronize do ... end を def する
    synchronized

などを追加してみました。
どれがアプリを書くときに有効か、いろいろ試してるところです。
# (3),(4)の実装がちょっと怪しいけどそれなりに動いてます。

mutex_m の様にオブジェクト自身に lock をかける場合、
(1) があるとややうれしいかも。
深く考えずにメソッドの中をsynchronize do .. end できるので。


# 使用例
  class Foo
    include MutexO_m

    def initialize
      super
      @foo = nil
      @bar = nil
      @count = 0
    end
    synchronize_accessor(:foo)	# synchronizeする accessor
    lock_accessor("bar")	# lockしてないと例外が起きる accessor

    def commit
      in_synchronize		# lockしてないと例外が起きるよ!
      p [@foo, @bar]
    end

    def sleep_and_set	    	# 強引なサンプル
      sleep 0.5
      @foo = @foo + @foo
      sleep 0.5
      @bar = @bar + @foo
      [@foo, @bar]
    end

    synchronized :sleep_and_set	# synchronizeで同期されます。
  end

  f = Foo.new
  f.foo = 1
  p f
  f.synchronize do 
    f.foo = 3		# 二重に synchronizeするけど平気 
    f.bar = 2		# synchronize中なので例外起きない
    f.commit
  end
  p f
  begin
    f.bar = 4		# lockしてないので例外
  rescue ThreadError
    p $!
  end
  p f

  Thread.new do
    p f.sleep_and_set	# synchronizedしてあるので安全
  end
  sleep 0.2
  f.foo = 5		# sleep_and_set が完了してから変更

  sleep 2
  p f


-- mutexo_m.rb module MutexO_m def MutexO_m.append_features(cl) super unless cl.instance_of?(Module) cl.module_eval %q{ alias locked? mu_locked? alias lock mu_lock alias unlock mu_unlock alias try_lock mu_try_lock alias synchronize mu_synchronize alias in_synchronize mu_in_synchronize } end def cl.synchronize_reader(attr) begin attr = attr.id2name rescue NameError end module_eval("def #{attr}; synchronize do return @#{attr} end; end") end def cl.synchronize_writer(attr) begin attr = attr.id2name rescue NameError end module_eval("def #{attr}=(p); synchronize do @#{attr}=p end; end") end def cl.synchronize_accessor(attr) synchronize_reader(attr) synchronize_writer(attr) end def cl.lock_reader(attr) begin attr = attr.id2name rescue NameError end module_eval("def #{attr}; mu_in_synchronize; return @#{attr}; end") end def cl.lock_writer(attr) begin attr = attr.id2name rescue NameError end module_eval("def #{attr}=(p); mu_in_synchronize; @#{attr}=p ; end") end def cl.lock_accessor(attr) lock_reader(attr) lock_writer(attr) end def cl.synchronized(method) begin method = method.id2name rescue NameError end org = "_mu_#{method}" module_eval("alias #{org} #{method}") module_eval("def #{method}; synchronize do #{org} end; end") private(org) end return self end def MutexO_m.extend_object(obj) super obj.mu_extended end def mu_extended unless (defined? locked? and defined? lock and defined? unlock and defined? try_lock and defined? synchronize) eval "class << self alias locked? mu_locked? alias lock mu_lock alias unlock mu_unlock alias try_lock mu_try_lock alias synchronize mu_synchronize alias in_synchronize mu_in_synchronize end" end initialize end # locking def mu_synchronize return yield if @mu_locked == Thread.current begin mu_lock yield ensure mu_unlock end end def mu_locked? @mu_locked ? true : false end def mu_try_lock result = false Thread.critical = true unless @mu_locked @mu_locked = Thread.current result = true end Thread.critical = false result end def mu_lock while (Thread.critical = true; @mu_locked) @mu_waiting.push Thread.current Thread.stop end @mu_locked = Thread.current mu_on_lock Thread.critical = false self end def mu_unlock return unless @mu_locked Thread.critical = true wait = @mu_waiting @mu_waiting = [] @mu_locked = nil mu_on_unlock Thread.critical = false for w in wait w.run end self end def mu_in_synchronize raise(ThreadError, 'no lock') unless @mu_locked == Thread.current end private # fook def mu_on_lock end def mu_on_unlock end def initialize(*args) ret = super @mu_waiting = [] @mu_locked = nil return ret end end