T
Tassilo Horn
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
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