1 / 29

Concurrency , Dining Philosophers Lecture 14

Concurrency , Dining Philosophers Lecture 14. COMP 201. What is a Concurrent Program?. A sequential program has a single thread of control.

harvey
Download Presentation

Concurrency , Dining Philosophers Lecture 14

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Concurrency,Dining PhilosophersLecture 14 COMP 201

  2. What is a Concurrent Program? A sequential program has a single thread of control. A concurrent program has multiple threads of control allowing it perform multiple computations in parallel and to control multiple external activities which occur at the same time.

  3. Why Concurrent Programming? • Performance gain from multiprocessing hardware • parallelism. • Increased application throughput • an I/O call need only block one thread. • Increased application responsiveness • high priority thread for user requests. • More appropriate structure • for programs which interact with the environment, control multiple activities and handle multiple events.

  4. Do I need to know about concurrent programming? Concurrency is widespread but error prone. • Therac - 25 computerised radiation therapy machine Concurrent programming errors contributed toaccidents causing deaths and serious injuries. • Mars Rover Problems with interaction between concurrent taskscaused periodic software resets reducing availability forexploration.

  5. Deadlock error

  6. Deadlock Concepts: system deadlock: no further progress four necessary & sufficient conditions Models: deadlock - no eligible actions Practice: blocked threads Aim: deadlock avoidance - to design systems where deadlock cannot occur.

  7. Deadlock: four necessary and sufficient conditions • Serially reusable resources: the processes involved share resources which they use under mutual exclusion. • Incremental acquisition: processes hold on to resources already allocated to them while waiting to acquire additional resources. • No pre-emption: once acquired by a process, resources cannot be pre-empted (forcibly withdrawn) but are only released voluntarily. • Wait-for cycle: a circular chain (or cycle) of processes exists such that each process holds a resource which its successor in the cycle is waiting to acquire.

  8. A E B C D Wait-for cycle Has A awaits B Has E awaits A Has B awaits C Has C awaits D Has D awaits E

  9. 3 2 2 1 3 4 1 4 0 0 Dining Philosophers Five philosophers sit around a circular table. Each philosopher spends his life alternately thinking and eating. In the centre of the table is a large bowl of spaghetti. A philosopher needs two forks to eat a helping of spaghetti. One fork is placed between each pair of philosophers and they agree that each will only use the fork to his immediate right and left.

  10. Dining Philosophers - model structure diagram Each FORK is a shared resource with actions get and put. When hungry, each PHIL must first get his right and left forks before he can start eating.

  11. Dining Philosophers

  12. Dining Philosophers

  13. ASML specification • A number of philosophers are sitting around a table. • Each one has a fork to the left and a fork to the right. • We model forks as structures with a unique field index. • structure Fork index as Integer

  14. Abstract class Philosopher • Philosophers are modelled as having a unique index, what state they are currently in and as being capable of two methods: • reporting whether they can make a state change (canMove) and • performing a state change (move). • Because the value of the field status can change, a Philosopher is a class and not a structure. abstractclass Philosopher var status as State = Thinking index as Integer canMove() as Boolean move()

  15. For simplicity we assume that there are a fixed number (four) of true philosophers (called simply philosophers below) and one fake philosopher called nobody. numPhilosophers as Integer = 4 nobody as Philosopher = undef Likewise we have four forks. numForks as Integer = numPhilosophers forks as Set of Fork = { Fork(i) | i ∈ {1..numForks} } The fork to the left of a philosopher has the same index as the philosopher. The fork to the right of a philosopher has the next higher index (modulo the number of philosophers). left(p as Philosopher) as Fork return Fork(p.index) right(p as Philosopher) as Fork return Fork(p.index mod numPhilosophers + 1)

  16. Philosopher’s lifecycle • A thinking philosopher has no forks. (Who needs a fork to think?) • A thinking philosopher may become hungry. • A hungry philosopher tries to grab the fork to the left and thus becomes a hungry philosopher with a left fork. • But one fork is not enough: a philosopher starts eating only upon obtaining both forks. • The fork to right can be obtained only if it is not being used. • From eating, there is only one place to go: back to thinking after putting down both forks.

  17. Thinking Hungry Eating HungryWithLeftFork A successful philosopher's lifecycle is this enum State Thinking; Hungry; HungryWithLeftFork; Eating Initially nobody has a fork. var holder as Map of Fork to Philosopher = { f ↦ nobody | f ∈ forks }

  18. Greedy Philosophers • A greedy philosopher never puts down a fork until (s)he has eaten and starts thinking. • This can lead to deadlock. • The behaviour has been made a little fancier by introducing a random amount of thinkingand eating for a fixed amount of time • a thinking philosopher will remain thinking about 80 percent of the time.

  19. class greedyPhilosopher extends Philosopher varbitesas Integer = 0 move() matchstatusThinking : if (any i | i ∈ {1..10}) < 3 then// usually they prefer to thinkstatus := Hungry Hungry : if holder(left(me)) = nobody then holder(left(me)) := mestatus := HungryWithLeftFork HungryWithLeftFork : if holder(right(me)) = nobody then holder(right(me)) := mestatus := Eating bites := 3 // the fixed number of bitesEating : ifbites> 0 thenbites := bites - 1 else holder(left(me)) := nobody holder(right(me)) := nobody status := Thinking

  20. Extracting the conditions from the method move yields the function canMove which indicates whether the philosopher can make a state change or not. class greedyPhilosopher... canMove() as Boolean return status = Thinking ∨ (status = Hungry ∧ holder(left(me)) = nobody) ∨ (status = HungryWithLeftFork ∧ holder(right(me)) = nobody) ∨ status = Eating asString() as String return "Greedy #" + index

  21. Generous Philosophers • A generous philosopherdoes not insist on following a successful philosophical life. • After picking up the left fork, but finding that the right fork is not available, a generous philosopher drops the left fork and goes back to think some more. • So if all philosophers are generous, then there is no deadlock, but starvation is possible.

  22. class generousPhilosopher extends Philosopher move() matchstatusThinking : status := Hungry Hungry : if holder(left(me)) = nobody then holder(left(me)) := mestatus := HungryWithLeftFork HungryWithLeftFork : if holder(right(me)) = nobody then holder(right(me)) := mestatus := Eating else// someone else is holding the right fork put // the left one down and try again another time holder(left(me)) := nobody status := Thinking Eating : holder(left(me)) := nobody holder(right(me)) := nobody status := Thinking

  23. Notice thatthe conditions which indicate whether a generous philosopher can make a state change or not are more liberal than those for greedy philosophers. class generousPhilosopher... canMove() as Boolean return status = Thinking ∨ (status = Hungry ∧ holder(left(me)) = nobody) ∨ status = HungryWithLeftFork ∨ status = Eating asString() as String return "Generous #" + index

  24. Thinking Hungry Eating HungryWithLeftFork A successful generousphilosopher's lifecycle is this

  25. The Scheduler Here is one possible scheduler: • From the set that it is given, • it chooses a philosopher that can make a state transition and then • fires the state transition. • If no philosopher can make a step, then • the system is deadlocked and • an exception is thrown.

  26. structure deadlockException implements RuntimeException message as String describe()as String return "Deadlock: " + message schedule(ps as Set of Philosopher, i as Integer) choose p ∈ ps where p.canMove() step currentStatus = p.status p.move() step WriteLine(p + " was " + currentStatus + ", but now is " + p.status) ifnonethrow deadlockException("after " + i + " steps")

  27. The Main Program • The main program tries to run the above schedule 1000 times, and is ready to catch the exception thrown if the system deadlocks. • You may choose which type of philosopher to schedule, just comment out one of the "greedy" or "generous" lines in the code.

  28. The Main Program (code) Main() phils = { new greedyPhilosopher(i) as Philosopher | i ∈ [1..numPhilosophers] } //phils = { new generousPhilosopher(i) as Philosopher | i ∈ [1..numPhilosophers] } trystepforeachi∈ [1..1000] schedule( phils, i ) catch d as deadlockException : WriteLine(d.describe())

  29. Summary • Concepts • deadlock: no futher progress • four necessary and sufficient conditions: • serially reusable resources • incremental acquisition • no preemption • wait-for cycle • Models • no eligable actions (analysis gives shortest path trace) • Practice • blocked threads Aim: deadlock avoidance - to design systems where deadlock cannot occur.

More Related