Rubyで結城浩せんせいのJavaマルチスレッド本 8 # Read-Write Lock
rubyで書いてみた
#!/usr/bin/env ruby require 'thread' # Read Write Lock class ReadWriteLock def initialize @reading_readers = 0 @waiting_writers = 0 @writing_writers = 0 @prefere_writers = true @m = Mutex.new @cv = ConditionVariable.new end def read_lock @m.synchronize { while( @writing_writers > 0 || (@prefere_writers && @waiting_writers > 0) ) do @cv.wait(@m) end @reading_readers = @reading_readers + 1 } end def read_unlock @m.synchronize { @reading_readers = @reading_readers - 1 @prefere_writers = true @cv.broadcast } end def write_lock @m.synchronize{ @waiting_writers = @waiting_writers + 1 begin while( @reading_readers > 0 && @waiting_writers > 0 ) do @cv.wait(@m) end ensure @waiting_writers = @waiting_writers - 1 end @waiting_writers = @waiting_writers + 1 } end def write_unlock @m.synchronize { @waiting_writers = @waiting_writers - 1 @prefere_writers = true @cv.broadcast } end end class DataClass def initialize @lock = ReadWriteLock.new @buffer = (1..10).map{"*"}.join end def read @lock.read_lock begin c= self.doRead ensure @lock.read_unlock end c end def write c @lock.write_lock begin self.doWrite c ensure @lock.write_unlock end end def doRead str = @buffer self.slowly str end def doWrite c @buffer = (1..10).map{ c }.join self.slowly end def slowly sleep 50.to_f/1000 end end class WriterThread < Thread def initialize data, filter @data = data @filter = filter @index = 0 super{ while true do c = self.next_char.chr @data.write c sleep rand 2 end } end def next_char c = @filter[@index] @index = @index + 1 if( @index < @filter.length ) @index = 0 if( @index >= @filter.length ) return c end end class ReaderThread < Thread def initialize data @data = data super{ while true do c = @data.read puts self.to_s + " read #{c}" end } end end data = DataClass.new threads = [ ReaderThread.new(data), ReaderThread.new(data), ReaderThread.new(data), ReaderThread.new(data), ReaderThread.new(data), WriterThread.new(data ,("A".."Z").map.join), # WriterThread.new(data ,("a".."z").map.join), # ] threads.each{|t| t.join} puts "End"
ロックの衝突
スレッド1 | スレッド2 | |
read | read | 並行 |
write | read | 衝突 |
write | write | 衝突 |
ruby添付ライブラリ
添付ライブラリにWrite/Readのロックを提供するパッケージがあるようだ。試してない。