In: Computer Science
We consider the dining philosophers problem. If all philosophers pick up their left fork, that causes deadlock.
Question: If one (and only one) of the philosophers instead tries to pick up their right fork first, can this system still deadlock? Why/ why not?
1. If only one of the philosophers pickup their right forks, this may remove the deadlock but it might cause starvation.
Ex. If 2 philosophere eat and think very fast and they are sitting in front of each other on the table, then the other 3 philosophers might be in a state of starving.
2. Other way to avoid the deadlock is :
3. The forkd will be numbered from 1 through 5 and each philosopher will always pick up the lower numbered for first, and then the higher numbered fork, from among the 2 forks they plan to use. The order in which each philosopher puts down the forks does not matter. In this case, if 4 of the 5 philosophers imultaneously pick up their lower-numbered fork, only the highest-numbered fork will remain on the table, so the fifth philosopher will not be able to pick up any fork. Moreover, only one philosopher will have access to that highest-numbered fork, so they will be able to eat using two forks.
Threading Solutions :
require 'thread'
class Philosopher
def initialize(name, left, right)
@name = name
@left = left
@right = right
@has_left = false
@has_right = false
@plates = 0
end
def pick_up_left(chopstick)
if chopstick.locked?
@has_left = false
puts "Philosopher #{@name} couldn't pick up the left chopstick"
else
chopstick.lock
@has_left = true
puts "Philosopher #{@name} picked up a left chopstick."
end
end
def pick_up_right(chopstick)
if chopstick.locked?
@has_right = false
puts "Philosopher #{@name} couldn't pick up the right chopstick"
else
chopstick.lock
@has_right = true
puts "Philosopher #{@name} picked up a right chopstick."
end
end
def eat
until @plates == 5 # arbitrarily, a meal == 5 plates
pick_up_left(@left)
pick_up_right(@right)
if @has_left && @has_right
puts "Philosopher #{@name} is eating now."
@plates += 1
@left.unlock
@right.unlock
elsif @has_left
@left.unlock
puts "Philosopher #{@name} is putting down the left chopstick."
elsif @has_right
@right.unlock
puts "Philosopher #{@name} is putting down the right chopstick."
end
end
end
end
class Meal
def initialize(num) # num is the number of philosophers
@chopsticks = []
num.times { @chopsticks << Mutex.new }
@philosophers = []
(0..(num-2)).each { |i| @philosophers << Philosopher.new(i, @chopsticks[i], @chopsticks[i+1]) }
#handle special case philospher who uses first and last chopstick in list
@philosophers << Philosopher.new(num-1, @chopsticks[num-1], @chopsticks[0])
@threads = []
@philosophers.each do |p|
@threads << Thread.new { p.eat }
end
@threads.each {|t| t.join}
end
end
m = Meal.new(12)