Skip to content

Instantly share code, notes, and snippets.

@egonSchiele
Created May 16, 2013 18:20
Show Gist options
  • Save egonSchiele/5593864 to your computer and use it in GitHub Desktop.
Save egonSchiele/5593864 to your computer and use it in GitHub Desktop.
Dining philosophers using locks in Ruby. This implements a Waiter who is in charge of forks.
require 'thread'
class Waiter
def initialize
@mutex = Mutex.new
end
def can_eat? philosopher
left = philosopher.left_fork
right = philosopher.right_fork
@mutex.synchronize do
if !left.used && !right.used
left.used = true
right.used = true
return true
else
return false
end
end
end
def stop_eating philosopher
@mutex.synchronize do
philosopher.left_fork.used = false
philosopher.right_fork.used = false
end
end
end
class Philosopher
attr_accessor :left_fork, :right_fork
def initialize(name, left_fork, right_fork, waiter)
@name = name
@left_fork = left_fork
@right_fork = right_fork
@waiter = waiter
think
end
def think
puts "Philosopher #@name is thinking..."
sleep(rand())
puts "Philosopher #@name is hungry..."
dine
end
def dine
while !@waiter.can_eat?(self)
think
end
puts "Philosopher #@name eats..."
sleep(rand())
puts "Philosopher #@name belches"
@waiter.stop_eating(self)
think
end
end
n = 5
forks = []
class Fork
attr_accessor :used
def initialize
@used = false
end
end
(1..n).each do |i|
forks << Fork.new
end
threads = []
waiter = Waiter.new
(1..n).each do |i|
threads << Thread.new do
if i < n
left_fork = forks[i]
right_fork = forks[i+1]
else
# special case for philosopher #5 because he gets forks #5 and #1
# and the left fork is always the lower id because that's the one we try first.
left_fork = forks[0]
right_fork = forks[n]
end
Philosopher.new(i, left_fork, right_fork, waiter)
end
end
threads.each {|thread| thread.join}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment