The dining philosophers problem. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 13

Similar documents
CS 361 Concurrent programming Drexel University Spring 2000 Lecture 14. The dining philosophers problem

EI 338: Computer Systems Engineering (Operating Systems & Computer Architecture)

Sections 01 (11:30), 02 (16:00), 03 (8:30) Ashraf Aboulnaga & Borzoo Bonakdarpour

Process Synchronization

Readers/Writers Problem. Readers/Writers: Scenario 1. Readers/Writers Problem. Today: Synchronization for Readers/Writers Problem

Roadmap. Readers-Writers Problem. Readers-Writers Problem. Readers-Writers Problem (Cont.) Dining Philosophers Problem.

Roadmap. Tevfik Ko!ar. CSC Operating Systems Fall Lecture - XI Deadlocks - II. Louisiana State University

Roadmap. Bounded-Buffer Problem. Classical Problems of Synchronization. Bounded Buffer 1 Semaphore Soln. Bounded Buffer 1 Semaphore Soln. Tevfik Ko!

5 Classical IPC Problems

CS370 Operating Systems

Operating Systems CMPSCI 377 Spring Mark Corner University of Massachusetts Amherst

Chapter 6: Synchronization. Chapter 6: Synchronization. 6.1 Background. Part Three - Process Coordination. Consumer. Producer. 6.

Process Synchronization. studykorner.org

Chapter 6: Process Synchronization

Process Synchronization

Semaphores (by Dijkstra)

Chapter 7: Process Synchronization!

Process Synchronization

Lecture 3: Intro to Concurrent Processing using Semaphores

Lesson 6: Process Synchronization

Process Synchronization

CS370 Operating Systems

CSE 4/521 Introduction to Operating Systems

Process Management And Synchronization

CS370: System Architecture & Software [Fall 2014] Dept. Of Computer Science, Colorado State University

Synchronization Principles II

Process Synchronization

Operating Systems. Designed and Presented by Dr. Ayman Elshenawy Elsefy

CHAPTER 6: PROCESS SYNCHRONIZATION

Lecture Topics. Announcements. Today: Concurrency (Stallings, chapter , 5.7) Next: Exam #1. Self-Study Exercise #5. Project #3 (due 9/28)

Midterm on next week Tuesday May 4. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 9

Synchronization Principles

Explain briefly how starvation may occur in process scheduling. (2 marks)

Interprocess Communication By: Kaushik Vaghani

CS 537 Lecture 8 Monitors. Thread Join with Semaphores. Dining Philosophers. Parent thread. Child thread. Michael Swift

Chapter 5: Process Synchronization. Operating System Concepts Essentials 2 nd Edition

Introduction to Operating Systems

Concept of a process

Synchronization. CS 475, Spring 2018 Concurrent & Distributed Systems

Chapter 5: Process Synchronization

Chapter 5: Process Synchronization. Operating System Concepts 9 th Edition

Dining Philosophers, Semaphores

Chapter 6: Process Synchronization. Operating System Concepts 9 th Edit9on

9/30/2014. CS341: Operating System High Level Construct: Monitor Deadlock Conditions Prevention, Avoidance Detection and Recovery

Roadmap. Tevfik Koşar. CSE 421/521 - Operating Systems Fall Lecture - X Deadlocks - I. University at Buffalo. Synchronization structures

Roadmap. Problems with Semaphores. Semaphores. Monitors. Monitor - Example. Tevfik Koşar. CSE 421/521 - Operating Systems Fall 2012

Paralleland Distributed Programming. Concurrency

Semaphores INF4140. Lecture 3. 0 Book: Andrews - ch.04 ( ) INF4140 ( ) Semaphores Lecture 3 1 / 34

Consistency: Strict & Sequential. SWE 622, Spring 2017 Distributed Software Engineering

Semaphores. Jinkyu Jeong Computer Systems Laboratory Sungkyunkwan University

Chapter 6: Process Synchronization. Operating System Concepts 8 th Edition,

Process Synchronization

Chapter 7: Process Synchronization. Background. Illustration

Quiz on Tuesday April 13. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 4. Java facts and questions. Things to try in Java

Chapter 7: Process Synchronization. Background

Background. Module 6: Process Synchronization. Bounded-Buffer (Cont.) Bounded-Buffer. Background

Process Synchronization

Chapter 6: Process Synchronization. Module 6: Process Synchronization

COMP 150-CCP Concurrent Programming. Lecture 12: Deadlock. Dr. Richard S. Hall

Chapter 5: Process Synchronization. Operating System Concepts 9 th Edition

CS3502 OPERATING SYSTEMS

Semaphore. Originally called P() and V() wait (S) { while S <= 0 ; // no-op S--; } signal (S) { S++; }

CS 361 Concurrent programming Drexel University Fall 2004 Lecture 8. Proof by contradiction. Proof of correctness. Proof of mutual exclusion property

Chapter 6: Process Synchronization

9/29/2014. CS341: Operating System Mid Semester Model Solution Uploaded Semaphore ADT: wait(), signal()

Concurrent Programming

Multithreaded Programming Part II. CSE 219 Stony Brook University, Department of Computer Science

Synchronization problems with semaphores

Chapter 6: Process Synchronization

CSC Systems Programming Fall Lecture - XIV Concurrent Programming. Tevfik Ko!ar. Louisiana State University. November 2nd, 2010

3C03 Concurrency: Starvation and Deadlocks

Chapter 5: Process Synchronization

Data Races and Deadlocks! (or The Dangers of Threading) CS449 Fall 2017

Silberschatz and Galvin Chapter 6

Only one thread can own a specific monitor

Reintroduction to Concurrency

Process Synchronization(2)

Week 7. Concurrent Programming: Thread Synchronization. CS 180 Sunil Prabhakar Department of Computer Science Purdue University

More Synchronization; Concurrency in Java. CS 475, Spring 2018 Concurrent & Distributed Systems

Deadlock and Monitors. CS439: Principles of Computer Systems September 24, 2018

Chapter 6 Synchronization

Pre- and post- CS protocols. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 7. Other requirements for a mutual exclusion algorithm

Process Synchronization

Operating Systems. Thread Synchronization Primitives. Thomas Ropars.

Chapter 6: Synchronization

Concurrent Object Oriented Languages

THREADS & CONCURRENCY

OS Process Synchronization!

Dealing with Issues for Interprocess Communication

Deadlock and Monitors. CS439: Principles of Computer Systems February 7, 2018

Process Synchronization. CISC3595, Spring 2015 Dr. Zhang

Back to synchronization

Concurrency pros and cons. Concurrent Programming Problems. Mutual Exclusion. Concurrency is good for users

Operating Systems Antonio Vivace revision 4 Licensed under GPLv3

Yet another synchronization problem

CSE Traditional Operating Systems deal with typical system software designed to be:

Distributed Real-Time Control Systems. Lecture 21 Condition Variables Typical ConcurrencyProblems

Operating systems. Lecture 12

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

Plan. Demos. Next Project. CSCI [4 6]730 Operating Systems. Hardware Primitives. Process Synchronization Part II. Synchronization Part 2

Transcription:

CS 361 Concurrent programming Drexel University Fall 2004 Lecture 13 Bruce Cha and Vera Zaychikr. All rights reserved by the author. Permission is given to students enrolled in CS361 Fall 2004 to reproduce these notes for their own use. The dining philosophers problem The dining philosophers problem involves five philosophers sitting at a round table with five forks interleaved between them. A bowl of spaghetti sits in the center of the table. Philosophers think for a while, become hungry, and try to eat. After eating for a while, a philosopher is ready to think again and the cycle repeats. A philosopher needs both forks to eat, the one on its right and the on its left. Sometimes the problem is presented with chopsticks instead of forks to emphasize that a philosopher needs both at the same time to eat. Only one philosopher can use a fork at a time. page 1 page 2 Constraints on the dining philosophers Avoid: deadlock (each philosopher holding a fork and refusing to relinquish it). Also, starvation (literally). Also, favoritism. Desirable goal: attain maximal parallelism (a hungry philosopher eats if its forks are not being used by other philosophers to eat). Although it looks contrived, it exemplifies a typical kind of synchronization problem, where there are overlapping sets of resources whose use must be coordinated. Dining philosophers: one solution using semaphores Central server object that records states of philosophers. Avoids deadlock/livelock, but doesn t address the issue of starvation by a philosopher page 3 page 4 page 5 Approach taken by solution A philosopher thinks for a random period of time, then becomes hungry. The philosopher then asks the central server for its forks. The central server checks the availability of the forks by examining the states of the hungry philosopher s two neighbors. If neither neighbor is eating, the hungry philosopher eats. Otherwise he waits, through P(self[i]). (One semaphore per philosopher.) page 6 Solution, cont. Once a philosopher obtains its two forks, it eats for a random amount of time, put down the forks, and then repeats the cycle. When a philosopher puts down his forks, the central server checks the philosopher s two neighbors with calls to the test method to see if either is hungry. If either is hungry and its two forks are available, the neighbor is unblocked with V(self[k]).

Dining philosophers server class DiningServer extends MyObject { private static final int // States THINKING = 0, HUNGRY = 1, EATING = 2; private int numphils = 0; private int[] state = null; private BinarySemaphore[] self = null; // array of sem. private BinarySemaphore mutex = null; public DiningServer(int numphils) { super("diningserver for " + numphils + " philosophers"); this.numphils = numphils; state = new int[numphils]; for (int i = 0; i < numphils; i++) state[i] = THINKING; self = new BinarySemaphore[numPhils]; for (int i = 0; i < numphils; i++) self[i] = new BinarySemaphore(0); mutex = new BinarySemaphore(1); page 7 Dining philosophers server, cont. private final int left(int i) { return (numphils + i - 1) % numphils; // wraparound indexing private final int right(int i) { return (i + 1) % numphils; public void takeforks(int i) { // when want to eat test(i); // will do a V(self[i]) if okay to eat P(self[i]); public void putforks(int i) { // when done eating state[i] = THINKING; test(left(i)); // may do release -- V -- for left test(right(i)); // may do V for right page 8 Dining philosophers server, cont. private void test(int k) { if (state[left(k)]!= EATING && state[right(k)]!= EATING && state[k] == HUNGRY) { state[k] = EATING; V(self[k]); page 9 Dining philosophers sample output /*... Example compile and run(s) age()=3960, Philosopher 0 is eating for 247 ms age()=4120, Philosopher 1 wants to eat D:\>javac dphi.java dpdr.java age()=4180, Philosopher 0 is thinking for 1642 ms age()=4180, Philosopher 1 is eating for 787 ms D:\>java DiningPhilosophers -R10 4 1 4 1 4 1 4 1 4 1 age()=5000, Philosopher 1 is thinking for 2828 ms DiningPhilosophers: numphilosophers=5, runtime=10 age()=5170, Philosopher 3 wants to eat Philosopher 0 is alive, napthink=4000, napeat=1000 age()=5170, Philosopher 3 is eating for 559 ms Philosopher 1 is alive, napthink=4000, napeat=1000 age()=5440, Philosopher 4 wants to eat Philosopher 2 is alive, napthink=4000, napeat=1000 age()=5720, Philosopher 3 is thinking for 319 ms Philosopher 3 is alive, napthink=4000, napeat=1000 age()=5720, Philosopher 4 is eating for 850 ms Philosopher 4 is alive, napthink=4000, napeat=1000 age()=5830, Philosopher 0 wants to eat All Philosopher threads started age()=6050, Philosopher 3 wants to eat age()=110, Philosopher 0 is thinking for 3816 ms age()=6270, Philosopher 2 wants to eat age()=110, Philosopher 1 is thinking for 2079 ms age()=6270, Philosopher 2 is eating for 33 ms age()=110, Philosopher 2 is thinking for 2646 ms age()=6320, Philosopher 2 is thinking for 92 ms age()=170, Philosopher 3 is thinking for 560 ms age()=6430, Philosopher 2 wants to eat age()=170, Philosopher 4 is thinking for 761 ms age()=6430, Philosopher 2 is eating for 612 ms age()=720, Philosopher 3 wants to eat age()=6600, Philosopher 4 is thinking for 3242 ms age()=720, Philosopher 3 is eating for 717 ms age()=6600, Philosopher 0 is eating for 320 ms age()=940, Philosopher 4 wants to eat age()=6930, Philosopher 0 is thinking for 3193 ms age()=1430, Philosopher 3 is thinking for 1653 ms age()=7040, Philosopher 2 is thinking for 3221 ms age()=1430, Philosopher 4 is eating for 913 ms age()=7040, Philosopher 3 is eating for 142 ms age()=2200, Philosopher 1 wants to eat age()=7200, Philosopher 3 is thinking for 2902 ms age()=2200, Philosopher 1 is eating for 86 ms age()=7800, Philosopher 1 wants to eat age()=2310, Philosopher 1 is thinking for 1797 ms age()=7800, Philosopher 1 is eating for 553 ms age()=2370, Philosopher 4 is thinking for 3052 ms age()=8410, Philosopher 1 is thinking for 3382 ms age()=2810, Philosopher 2 wants to eat age()=9840, Philosopher 4 wants to eat age()=2810, Philosopher 2 is eating for 442 ms age()=9840, Philosopher 4 is eating for 678 ms age()=3140, Philosopher 3 wants to eat age()=10110, Philosopher 3 wants to eat age()=3300, Philosopher 2 is thinking for 3003 ms age()=10110, Philosopher 0 wants to eat age()=3300, Philosopher 3 is eating for 465 ms age()=10110, time to stop the Philosophers and exit age()=3740, Philosopher 3 is thinking for 1381 ms... end of example run(s) */ age()=3960, Philosopher 0 wants to eat page 10 Philosopher class Philosopher class, con t private void think() { int napping; napping = 1 + (int) random(napthink); System.out.println("age()=" + age() + ", " + getname() class Philosopher extends MyObject implements Runnable { + " is thinking for " + napping + " ms"); private int id = 0; nap(napping); private int napthink = 0; // both are in private int napeat = 0; // milliseconds private DiningServer ds = null; private void eat() { public Philosopher(String name, int id, int napthink, int napping; int napeat, DiningServer ds) { napping = 1 + (int) random(napeat); super(name + " " + id); System.out.println("age()=" + age() + ", " + this.id = id; getname() this.napthink = napthink; + " is eating for " + napping + " ms"); this.napeat = napeat; this.ds = ds; nap(napping); System.out.println(getName() + " is alive, napthink=" + napthink + ", napeat=" + napeat); new Thread(this).start(); // self-starting object page 11 page 12

page 13 Philosopher class cont. public void run() { while (true) { think(); // Life is thinking System.out.println("age()=" + age() + ", " + getname() + " wants to eat"); ds.takeforks(id); eat(); // and eating ds.putforks(id); D.P. driver (main) class DiningPhilosophers extends MyObject { public static void main(string[] args) { // parse command line options, if any, to override defaults GetOpt go = new GetOpt(args, "Up:R:"); go.opterr = true; String usage = "Usage: -p numphilosophers" + " -R runtime napthink[i] napeat[i] i=0,1,..."; int ch = -1; int numphilosophers = 5; int runtime = 60; // seconds while ((ch = go.getopt())!= go.opteof) { if ((char)ch == 'U') { System.out.println(usage); System.exit(0); else if ((char)ch == 'p') numphilosophers = go.processarg(go.optargget(), numphilosophers); else if ((char)ch == 'R') runtime = go.processarg(go.optargget(), runtime); else { System.err.println(usage); System.exit(1); System.out.println("DiningPhilosophers: numphilosophers=" + numphilosophers + ", runtime=" + runtime); // process non-option command line arguments int[] napthink = new int[numphilosophers]; int[] napeat = new int[numphilosophers]; for (int i = 0; i < numphilosophers; i++) { napthink[i] = 8; napeat[i] = 2; // defaults int argnum = go.optindexget(); for (int i = 0; i < numphilosophers; i++) { napthink[i] = go.tryarg(argnum++, napthink[i]); napeat[i] = go.tryarg(argnum++, napeat[i]); page 14 page 15 D.P. driver cont. // create the DiningServer object DiningServer ds = new DiningServer(numPhilosophers); // create the Philosophers (they have self-starting // threads) for (int i = 0; i < numphilosophers; i++) new Philosopher("Philosopher", i, napthink[i]*1000, napeat[i]*1000, ds); System.out.println("All Philosopher threads started"); // let the Philosophers run for a while nap(runtime*1000); System.out.println("age()=" + age() + ", time to stop the Philosophers and exit"); System.exit(0); page 16 Avoiding deadlock Another way to avoid deadlock is to make sure that at most NUMPHILS-1 philosophers are given permission to pick up a fork. That ensures that one of them will always be able to pick up two forks. Avoiding deadlock class DiningServer extends MyObject { private static final int THINKING = 0, HUNGRY = 1, EATING = 2; private int numphils = 0; private int[] state = null; private BinarySemaphore[] fork = null; private CountingSemaphore room = null; public DiningServer(int numphils) { super("diningserver for " + numphils + " philosophers"); this.numphils = numphils; state = new int[numphils]; for (int i = 0; i < numphils; i++) state[i] = THINKING; fork = new BinarySemaphore[numPhils]; for (int i = 0; i < numphils; i++) fork[i] = new BinarySemaphore(1); room = new CountingSemaphore(numPhils-1); System.out.println("Dining room limited to " + (numphils- 1)); page 17 page 18 The takeforks code private final int left(int i) { return (numphils + i - 1) % numphils; private final int right(int i) { return (i + 1) % numphils; public void takeforks(int i) { P(room); P(fork[i]); P(fork[right(i)]); // since the counting semaphore room is set to numphils-1, one // philosopher is excluded from trying to pick up a fork if // all should try at the same // time. state[i] = EATING; public void putforks(int i) { V(fork[i]); V(fork[right(i)]); V(room); state[i] = THINKING;

Notes on Stalling s solution Prevents starvation because a philosopher picks up a left fork and doesn t put it down until it eats. Prevents deadlock because only N-1 philosophers are allowed to pick up forks (the use of the room counting semaphore), which prevents deadlock. Maximal parallelism The problem with Stalling s solution is that it doesn t allow maximal parallelism one person is eating, the rest are all blocked waiting for their other fork. Increased parallelism if every other philosopher eating instead of just one. There s another solution where one philosopher is designated as odd and picks up the forks in reverse order from the others. Then deadlock cannot occur but again maximal parallelism isn t achieved. page 19 page 20 Another non-maximal solution public void takeforks(int i) { if (i > 0) { P(fork[i]); P(fork[right(i)]); else { P(fork[right(i)]); P(fork[i]); state[i] = EATING; Avoiding starvation This solution avoids deadlock but doesn t guarantee that no philosopher will starve. Odd philosopher out takes the fork in his/her other hand. Still doesn t achieve maximal parallelism. page 21 page 22 Exercise: avoid starvation Modify the program so that it is starvation-free. One way to do this is to add another state starving and not let a hungry philosopher eat if it has a starving neighbor. A hungry philosopher enters this state if its neighbors have put down their forks and the philosopher under consideration has not been able to eat. Exercise: avoid starvation You must change the state of a philosopher only when one of its neighbors puts down its forks. Don t make a philosopher starve the first time it tries to pick up its forks and it can t. Can t have two neighboring philosophers starving at the same time because either they will deadlock or you will still have starvation. page 23 page 24

Exercise: avoid starvation (alternatives) Or you can count the number of times it has not been able to pick up its forks, or base it on how many times each fork has been picked up. Or assign ticket numbers like Lamport s algorithm. Database reader/writer problem The readers and writers problem: readers may read a database simultaneously as long as no writer writes Only one writer at a time may write (if there are no active readers). Attain: maximal parallelism (readers may read simultaneously if there is no writing), data integrity (only one writer at a time if no readers are reading). Possible additional goal: avoid writer starvation (locked out of writing because readers are always coming along to read). page 25 page 26 page 27 Database reader/writer solution class Database extends MyObject { private int numreaders = 0; private BinarySemaphore mutex = new BinarySemaphore(1); private BinarySemaphore ok = new BinarySemaphore(1); public Database() { super("database"); Reader code public void startread(int i) { numreaders++; if (numreaders == 1) { System.out.println("age=" + age() + " reader " + i + " waiting to read, numreaders=" + numreaders); P(ok); System.out.println(" age=" + age() + " reader " + i + " has begun reading, numreaders=" + numreaders); public void endread(int i) { numreaders--; System.out.println(" age=" + age() + " reader " + i + " finished reading, numreaders=" + numreaders); if (numreaders == 0) V(ok); page 28 Writer code Notes on reader/writer solution public void startwrite(int i) { P(ok); System.out.println(" age=" + age() + " WRITER " + i + " has begun Writing"); public void endwrite(int i) { System.out.println(" age=" + age() + " WRITER " + i + " has finished Writing"); V(ok); Only the first reader should lock the ok lock. The last reader should unlock it when it finishes its read. Then the Writers can write. Starvation of writers might occur. page 29 page 30