7
\$\begingroup\$

The point of the puzzle is to learn about livelocks:

Create a multi-threaded (or a multi-process) program, whose threads (processes) indefinitely try to wait for each other and never finish. Unlike a deadlock situation, the state of threads (processes) in a livelock constantly change as they try to resolve the situation, but never succeeding.

The task isn't to create a shortest or a simplest solution. Try to create a solution that resembles a real situation, something that looks like a genuine piece of code, but with some kind of an error that creates the livelock.

This is a popularity contest. The most up-voted answer in ~10 days wins.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

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)
\$\endgroup\$
1
\$\begingroup\$

Game Maker Language

Script add:

subtract=argument0
add(not(subtract))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.