From: Markus Date: 2004-10-09T00:54:48+09:00 Subject: Re: Problems with my first multithreaded Rupy programm Try taking the cv.broadcast and the Thread.stop out of the mutex syncronize block (e.g., let go before you tell the others to start). -- Markus On Fri, 2004-10-08 at 08:14, Tassilo Horn wrote: > Hi, > > I'm trying to get into Ruby and today it's time for > multithreading. Therefore I wanted to write a program which does this: > > In a tearoom there are three thirsty drinkers. To cook a tea one > needs water, tea and a cup. Every one of these three drinkers > has one of those items with him. > Every time the waiter is called he puts two items on the > table. Now one drinker has all the items he needs and cooks his > tea. After that he calls the waiter and the fun begins again... > > Ok, here's what I wrote so far and what produces this output: > > ,---- > | (%:~/tmp/Teadrinker)- ./TeaRoom.rb > | WAITER: Looking at the table! > | WAITER: Oh, nothing on the table! > | WAITER: Putting 1 and 2 on the table. > | deadlock 0x4023b798: sleep:J(0x4022603c) (main) - ./TeaRoom.rb:94 > | deadlock 0x40225e70: sleep:- - /usr/lib/ruby/1.8/thread.rb:96 > | deadlock 0x40225efc: sleep:- - /usr/lib/ruby/1.8/thread.rb:96 > | deadlock 0x40225f88: sleep:- - /usr/lib/ruby/1.8/thread.rb:96 > | deadlock 0x4022603c: sleep:- - ./TeaRoom.rb:31 > | ./TeaRoom.rb:31: Thread(0x4022603c): deadlock (fatal) > `---- > > <----- CODE -----> > > #! /usr/bin/env ruby > > require 'thread' > > # For synchronisation > mutex = Mutex.new > cv = ConditionVariable.new > > # items on the table: > # 0: cup > # 1: water > # 2: tea > table = [] > > 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 the waiting tea drinkers > cv.broadcast > Thread.stop > } > end > } > > # Mike has a cup (0) > mike = Thread.new { > while true > mutex.synchronize { > cv.wait(mutex) > if table.include?(1) and table.include?(2) > puts "MIKE: Water and tea on table. I'll cook my tea." > table = [] > sleep 3 > puts "MIKE: Drinking my tea. Calling the waiter." > # Wake up the waiter-Thread > waiter.wakeup > sleep 3 > puts "MIKE: Now I will read my newspaper." > else > puts "MIKE: Not what I need." > end > } > end > } > > # Al has water (1) > al = Thread.new { > while true > mutex.synchronize { > cv.wait(mutex) > if table.include?(0) and table.include?(2) > puts "AL: Cup and tea on table. I'll cook my tea." > table = [] > sleep 3 > puts "AL: Drinking my tea. Calling the waiter." > # Wake up the waiter-Thread > waiter.wakeup > sleep 3 > puts "AL: Now I will read my newspaper." > else > puts "AL: Not what I need." > end > } > end > } > > # Ed has tea (2) > ed = Thread.new { > while true > mutex.synchronize { > cv.wait(mutex) > if table.include?(0) and table.include?(1) > puts "ED: Cup and water on table. I'll cook my tea." > table = [] > sleep 3 > puts "ED: Drinking my tea. Calling the waiter." > # Wake up the waiter-Thread > waiter.wakeup > sleep 3 > puts "ED: Now I will read my newspaper." > else > puts "ED: Not what I need." > end > } > end > } > > waiter.join > > <----- END OF CODE -----> > > What's wrong with these lines? > > Much thanks in advance, > Tassilo