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)