Ruby
Based on the Dining Philosophers tale - 4 philosophers:
Five silent philosophers sit at a table around a bowl of spaghetti. A
fork is placed between each pair of adjacent philosophers. (An
alternative problem formulation uses rice and chopsticks instead of
spaghetti and forks.)
Each philosopher must alternately think and eat. However, a
philosopher can only eat spaghetti when he has both left and right
forks. Each fork can be held by only one philosopher and so a
philosopher can use the fork only if it's not being used by another
philosopher. After he finishes eating, he needs to put down both forks
so they become available to others. A philosopher can grab the fork on
his right or the one on his left as they become available, but can't
start eating before getting both of them.
class Fork
attr_reader :owner
def initialize
@mutex = Mutex.new
end
def pickup(new_owner)
@mutex.synchronize do
if @owner.nil?
@owner = new_owner
return true
end
return false
end
end
def release(owner)
@mutex.synchronize do
if @owner == owner
@owner = nil
return true
end
return false
end
end
end
class Philosopher
attr_reader :name, :hungry
attr_accessor :left_fork, :right_fork
def initialize(name, left_fork, right_fork)
@name = name
@hungry = true
@left_fork = left_fork
@right_fork = right_fork
end
def eat
while hungry
got_left = left_fork.pickup(self)
think
got_right = right_fork.pickup(self)
if got_left && got_right
@hungry = false
puts "#{name} has eaten!"
end
right_fork.release(self)
think
left_fork.release(self)
end
puts "#{name} ended"
end
def think
puts "#{name} thinks..."
sleep 1
end
end
fork = nil
philosophers = %w(aristotle plato confucius descartes).map { |p| Philosopher.new(p, fork, fork = Fork.new) }
philosophers[0].left_fork = fork
threads = philosophers.map do |p|
puts p.left_fork.pickup(p)
Thread.new {
p.eat
}
end
threads.map(&:join)