From: Markus Date: 2004-10-17T00:55:20+09:00 Subject: Re: Again some problem with my multithreaded teadrinker app --=-051zEIgjMhjMWwe+h154 Content-Type: text/plain Content-Transfer-Encoding: 7bit It still works for me. See attached. Diff it perhaps? -- Markus On Sat, 2004-10-16 at 08:04, Tassilo Horn wrote: > Markus writes: > > > I think (and this late in a long day for me, so I may be wrong) > > that the problem is that you are using broadcast to wake the drinkers. > > This causes a race condition (as they all assess the table contents "at > > once") and an eventual deadlock. > > This has come in my mind, too, but... > > > I tried a quick test of 1) replacing the broadcast with a signal, > > and 2) adding an else-clause so that the drinker re-signals if what he > > finds on the table is not what he's wanting. > > ....if I do exactly this it deadlocks even faster. > > > It makes sense & seems to work, but I'm too pooped to vouch for it > > beyond that. > > Hm, it makes sense to me, too. But how can it be that it works for you > but not for me? I use ruby-1.8.2_pre2. > > > -- Markus > > Thanks and regards, > > Tassilo --=-051zEIgjMhjMWwe+h154 Content-Disposition: attachment; filename=waiter Content-Type: text/plain; name=waiter; charset=UTF-8 Content-Transfer-Encoding: 7bit #! /usr/bin/env ruby require 'thread' # For synchronisation mutex = Mutex.new drinker_cv = ConditionVariable.new waiter_cv = ConditionVariable.new # items on the table: # 0: cup # 1: water # 2: tea table = [] items = %w{ Cup Water Tea } # min. 3 drinkers. if ARGV[0].to_i >= 3 drinkers_count = ARGV[0].to_i else drinkers_count = 3 end drinkers_count.times do |i| case i%3 when 0 # this drinker has water and tea needs = [1,2] when 1 # this drinker has a cup and tea needs = [0,2] when 2 # this drinker has a cup and water needs = [0,1] end Thread.new { puts "Starting Drinker#{i}" while true mutex.synchronize { drinker_cv.wait(mutex) # The things on the table are the things the waiter needs. if needs.sort == table.sort puts "Drinker#{i}: #{items[table[0]]} and #{items[table[1]]} on table. I'll cook my tea!" # The Drinker took the items from the table. Now it's empty # till the waiter puts new items on it. table = [] ##sleep 1 # (1) # puts "Drinker#{i}: Drinking my tea. I call the waiter again." # Wake up the waiter Thread waiter_cv.signal ##sleep 1 # (2) # puts "Drinker#{i}: Now I'll read my newspaper." else drinker_cv.signal end } end } end waiter = Thread.new { while true mutex.synchronize { puts "WAITER: Looking at the table!" if table.length == 0 puts "WAITER: Oh, nothing on the table!" #sleep 2 while table[0] == table[1] do table = [rand(3), rand(3)] end $stdout << "WAITER: Putting " << table[0] << " and " << table[1] << " on the table.\n" else puts "WAITER: Why did you call me???" end # Call waiting tea drinkers. drinker_cv.signal # (3) # puts "WAITER: Waiting for new appointments..." waiter_cv.wait(mutex) } end } waiter.join --=-051zEIgjMhjMWwe+h154--