Κλασικά Προβλήματα Συγχρονισμού (με σηματοφόρους) Ταυτόχρονος Προγραμματισμός 1

Σχετικά έγγραφα
Κρίσιμη Περιοχή Υπό Συνθήκη (Conditional Critical Regions) Ταυτόχρονος Προγραμματισμός 1

Προβλήματα Συγχρονισμού (με ελεγκτή) Ταυτόχρονος Προγραμματισμός 1

Ελεγκτές/Παρακολουθητές (Monitors) Ταυτόχρονος Προγραμματισμός 1

Υλοποίηση Σηματοφόρων

Προβλήματα Συγχρονισμού (με ελεγκτή) Ταυτόχρονος Προγραμματισμός 1

Σηματοφόροι (Σηματοφορείς) Ταυτόχρονος Προγραμματισμός 1

Ελεγκτές/Παρακολουθητές (Monitors) Ταυτόχρονος Προγραμματισμός 1

2.4 Κλασσικά Προβλήματα IPC

Σηματοφόροι (Σηματοφορείς) Ταυτόχρονος Προγραμματισμός 1

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

Συγχρονισμός & σηματοφόροι. Προγραμματισμός II 1

Λειτουργικά Συστήματα (ΗΥ222)

Λειτουργικά Συστήματα Η/Υ

Προσπέλαση σύνθετων δομών δεδομένων χωρίς καθολικό κλείδωμα

Διεργασίες (Processes)

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

Νήµαταστην Java. Συγχρονισµός νηµάτων Επικοινωνία νηµάτων Εκτελέσιµα αντικείµενα Νήµατα δαίµονες Οµάδες νηµάτων. Κατανεµηµένα Συστήµατα 11-1

Προσπέλαση σύνθετων δομών δεδομένων χωρίς καθολικό κλείδωμα

6. Αδιέξοδο. 1. Ορισμοί είδη πόρων. 3. Συνθήκες αδιεξόδου. 1. Πρόληψη 2. Αποφυγή 3. Ανίχνευση 5. Το πρόβλημα των συνδαιτημόνων φιλοσόφων

Αδιέξοδα Ανάθεση Πόρων (Deadlocks Resource Allocation)

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

Κλείδωμα αρχείων (file locking) Προγραμματισμός II 1

Αδιέξοδα Ανάθεση Πόρων (Deadlocks Resource Allocation)

Χώροι Πλειάδων (Tuple Spaces) Ταυτόχρονος Προγραμματισμός 1

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

Ορθότητα λειτουργίας τμημάτων λογισμικού & δομών δεδομένων υπό ταυτόχρονη εκτέλεση

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Λειτουργικά Συστήματα

Εργαστήριο 14. Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t)

Λειτουργικά Συστήματα. Ενότητα # 6: Αδιέξοδα Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Αγωγοί/Σωλήνες (Pipes) Προγραμματισμός II 1

Παράλληλη Επεξεργασία Κεφάλαιο 6 ο Σύγχρονος Παραλληλισμός

ΑΔΙΕΞΟΔΑ (Deadlocks) Παράδειγμα 1 Θανάσιμο αγκάλιασμα (deadly embrace)

Εισαγωγή στα Λειτουργικά Συστήματα

Σύγχρονη επικοινωνία με ανταλλαγή μηνυμάτων (CSP message passing model) Ταυτόχρονος Προγραμματισμός 1

Χώροι Πλειάδων (Tuple Spaces) Ταυτόχρονος Προγραμματισμός 1

Συστηματικός έλεγχος ορθότητας ταυτόχρονων προγραμμάτων μέσω γράφου καταστάσεων

Προγραμματισμός συστημάτων UNIX/POSIX

Λειτουργικά Συστήματα

Γιατί υϖάρχει τέτοια καθολική κατάσταση;

Λειτουργικά Συστήματα Η/Υ

Εντοπισμός αδιεξόδου. Κατανεμημένα Συστήματα 1

Διάλεξη 10: Αλγόριθμοι Αμοιβαίου Αποκλεισμού σε περιβάλλον ανταλλαγής μηνυμάτων. ΕΠΛ 432: Κατανεμημένοι Αλγόριθμοι

Συστηματικός έλεγχος ορθότητας ταυτόχρονων προγραμμάτων μέσω γράφου καταστάσεων

Ορθότητα λειτουργίας τμημάτων λογισμικού & δομών δεδομένων υπό ταυτόχρονη εκτέλεση

Διάλεξη 16: Σωροί. Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Ουρές Προτεραιότητας - Ο ΑΤΔ Σωρός, Υλοποίηση και πράξεις

Διάλεξη 9: Αλγόριθμοι Αμοιβαίου Αποκλεισμού με τη χρήση μεταβλητών Ανάγνωσης/Εγγραφής. ΕΠΛ 432: Κατανεμημένοι Αλγόριθμοι

Εισαγωγή στα Λειτουργικά Συστήματα

Παράλληλη Επεξεργασία

Διαδιεργασιακή επικοινωνία (inter-process communication IPC) Προγραμματισμός II 1

Διάλεξη 16: Σωροί. Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Ουρές Προτεραιότητας - Ο ΑΤΔ Σωρός, Υλοποίηση και πράξεις

Αμοιβαίος αποκλεισμός

Εργαστήριο ΔΙΕΡΓΑΣΙΕΣ - ΔΙΑΧΕΙΡΙΣΗ

Μη ανασταλτική/πολυπλεξία Ε/Ε (non-blocking/multiplexed I/O) Προγραμματισμός II 1

Επικοινωνία µεταξύ ιεργασιών και Σύνδροµες ιεργασίες

Καρακασίδης Αλέξανδρος Καστίδου Γεωργία Παπαφώτη Μαρία Πέτσιος Κων/νος Στέφανος Σαλτέας Καλογεράς Παναγιώτης. Threads in Java ΝΗΜΑΤΑ ΣΤΗ JAVA

Κλείδωμα αρχείων (file locking) Προγραμματισμός II 1

Διασυνδεδεμένες Δομές. Δυαδικά Δέντρα. Προγραμματισμός II 1

Ασύγχρονο Σύστηµα ιαµοιραζόµενης Μνήµης Το σύστηµα περιέχει n διεργασίες p 0,, p n-1 και m καταχωρητές R 0,, R m-1. Κάθε διεργασία µοντελοποιείται ως

Αξιόπιστη μεταφορά δεδομένων πάνω από αναξιόπιστο δίκτυο. Κατανεμημένα Συστήματα 1

Σύγχρονη επικοινωνία με ανταλλαγή μηνυμάτων (CSP message passing model) Ταυτόχρονος Προγραμματισμός 1

Νήµατα. Πολύ σηµαντικό

Εγγυημένη ποιότητα υπηρεσίας

Λειτουργικά Συστήματα. Ενότητα # 2: Διεργασίες και Νήματα Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Διάλεξη 26: Σωροί. Διδάσκων: Παναγιώτης Ανδρέου

Προβλήματα ταυτόχρονης εκτέλεσης (για νήματα με κοινή μνήμη)

Διασυνδεδεμένες Δομές. Λίστες. Προγραμματισμός II 1

Δομές Δεδομένων & Αλγόριθμοι

Λογικός τύπος Τελεστές σύγκρισης Λογικοί τελεστές Εντολές επιλογής Εμβέλεια Μαθηματικές συναρτήσεις Μιγαδικός τύπος ΔΕΥΤΕΡΗ ΔΙΑΛΕΞΗ

Αδιέξοδα (Deadlocks)

Λειτουργικά Συστήματα. Ενότητα # 2: Διεργασίες και Νήματα Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Γραμμικές Δομές Δεδομένων

Τμήμα Οικιακής Οικονομίας και Οικολογίας. Οργάνωση Υπολογιστών

Λειτουργικά Συστήματα

Διεργασίες (μοντέλο μνήμης & εκτέλεσης) Προγραμματισμός II 1

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Επισκόπηση Μαθήματος. Γραμμικές Δομές Δεδομένων. ΑΤΔ Ουρά Εναλλακτικοί Σχεδιασμοί Προγραμματισμός με Ενότητες Interface.h Implementation.

Αμοιβαίος αποκλεισμός με ασύγχρονη επικοινωνία (ανταλλαγή μηνυμάτων) Ταυτόχρονος Προγραμματισμός 1

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ. Αδιέξοδα

Αµοιβαίοςαποκλεισµός. Κατανεµηµένα Συστήµατα 03-1

Πληροφοριακά Συστήματα Διοίκησης Ενότητα 7: Διαγράμματα Καταστάσεων

ΠΛΗ111. Ανοιξη Μάθηµα 5 ο. Ουρά. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΡΟΣΟΜΟΙΩΣΗ ΔΙΕΡΓΑΣΙΩΝ ΧΡΗΣΙΜΟΠΟΙΩΝΤΑΣ ΤΟ ΛΟΓΙΣΜΙΚΟ EXTEND. 1 ο εργαστήριο Διοίκησης και Παραγωγής Έργων

Ορισµός Νήµα (thread) είναι µια ακολουθιακή ροή ελέγχου (δηλ. κάτι που έχει αρχή, ακολουθία εντολών και τέλος) σ ένα

Δυαδικά Δένδρα Αναζήτησης, Δένδρα AVL

Σειρά Προβλημάτων 4 Λύσεις

Κατανεμημένα Συστήματα

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι ΙΕΡΓΑΣΙΕΣ ΕΙΣΑΓΩΓΗ ΣΤΙΣ ΙΕΡΓΑΣΙΕΣ

Προγραμματισμός Ι (HY120)

ΔΙΕΡΓΑΣΙΕΣ. Λειτουργικά Συστήματα Ι. Διδάσκων: Καθ. Κ. Λαμπρινουδάκης ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι

Αξιόπιστη μεταφορά δεδομένων πάνω από αναξιόπιστο δίκτυο. Κατανεμημένα Συστήματα 1

Ουρές (Queues) FIFO A B C. Διαγραφή. Εισαγωγή. εµπρός. πίσω. πίσω. πίσω

Παραδείγματα Θεμάτων/Ασκήσεων Συστημάτων Ουρών Αναμονής

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ

Κεφάλαιο 2. Η δομή δεδομένων Σωρός και η Ταξινόμηση Σωρού (The Heap data structure and Heapsort) Έκδοση 1.3, 14/11/2014

Λειτουργικά Συστήματα (Λ/Σ)

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Κεφάλαιο 3: Λειτουργικά Συστήµατα

ΑΠΟΤΕΛΕΣΜΑΤΑ ΕΠΠΑΙΚ ΑΝΑ ΠΟΛΗ ΣΕΙΡΑ ΚΑΤΑΤΑΞΗΣ ΕΙΣΑΓΩΓΗ ΟΝΟΜΑ ΕΠΩΝΥΜΟ ΠΑΤΡΩΝΥΜΟ ΠΟΛΗ ΕΠΙΛΟΓΗΣ 1 NAI ΔΗΜΗΤΡΙΟΣ ΚΑΡΒΟΥΝΗΣ ΝΙΚΟΛΑΟΣ ΑΘΗΝΑ 2 NAI ΒΑΣΙΛΕΙΟΣ

Μάθημα 4 ο. Κρίσιμα Τμήματα και Αμοιβαίος Αποκλεισμός

Transcript:

Κλασικά Προβλήματα Συγχρονισμού (με σηματοφόρους) 1 lalis@inf.uth.gr

Παραγωγός-Καταναλωτής (με σηματοφόρους) 2 lalis@inf.uth.gr

Παραγωγός-καταναλωτής Νήματα που παράγουν / καταναλώνουν δεδομένα τα οποία τοποθετούν σε / παραλαμβάνουν από μια κοινή ενδιάμεση αποθήκη Η αποθήκη είναι ένας ΑΤΔ με λειτουργίες put: λειτουργεί πάντα (απεριόριστη χωρητικότητα) get: λειτουργεί μόνο αν η αποθήκη δεν είναι άδεια Επιθυμητός συγχρονισμός: ένας καταναλωτής πρέπει να μπλοκάρεται όταν (και όσο) η αποθήκη είναι άδεια, και να αφυπνίζεται με το που κάποιος παραγωγός τοποθετήσει δεδομένα στην αποθήκη 3 lalis@inf.uth.gr

λειτουργεί σωστά μόνο όταν η αποθήκη δεν είναι άδεια πρέπει να μπλοκάρει όσο η αποθήκη είναι άδεια 4 lalis@inf.uth.gr

Σκεπτικό Πρέπει να μετράμε τον αριθμό των δεδομένων που είναι διαθέσιμα στην αποθήκη ανά πάσα στιγμή Χρειαζόμαστε έναν «κατάλληλο» μετρητή προσθήκη δεδομένων: αύξηση μετρητή απομάκρυνση δεδομένων: μείωση μετρητή αναμονή καταναλωτή: όταν ο μετρητής είναι Ο μετρητής πρέπει να αυξομειώνεται σωστά υπό την ταυτόχρονη εκτέλεση των παραγωγών/καταναλωτών Αυτή η λειτουργικότητα αντιστοιχεί ακριβώς στην λειτουργικότητα ενός γενικού σηματοφόρου 5 lalis@inf.uth.gr

gsem avl; /* # δεδομένων στην αποθήκη */ init(avl,); παραγωγός: while (1) { /* produce d */ put(d); καταναλωτής: while (1) { down(avl); d=get(); up(avl); /* consume d */ 6 lalis@inf.uth.gr

Παρατήρηση Η λύση είναι σωστή ανεξάρτητα από τον αριθμό των νημάτων παραγωγού και καταναλωτή Αν οι λειτουργίες της αποθήκης put και get δεν είναι ασφαλείς υπό ταυτόχρονη εκτέλεση, τότε οι κλήσεις τους αποτελούν κρίσιμα τμήματα και πρέπει να προστατευτούν κατάλληλα Αυτό μπορεί να γίνει πολύ εύκολα μέσω ενός δυαδικού σηματοφόρου 7 lalis@inf.uth.gr

gsem avl; /* # δεδομένων στην αποθήκη */ bsem mtx; /* αμοιβαίος αποκλεισμός put,get */ init(avl,); init(mtx,1); παραγωγός: while (1) { /* produce d */ down(mtx); put(d); up(mtx); καταναλωτής: while (1) { down(avl); down(mtx); d=get(); up(mtx); up(avl); /* consume d */ 8 lalis@inf.uth.gr

Αποθήκη περιορισμένης χωρητικότητας Όταν η αποθήκη είναι γεμάτη δεν επιτρέπεται να κληθεί η put (αυτό θα οδηγούσε σε υπερχείλιση) Ο παραγωγός πρέπει (και αυτός) να μπλοκάρεται, (όταν η αποθήκη είναι γεμάτη) και να αφυπνίζεται όταν κάποιος καταναλωτής απομακρύνει δεδομένα Η σχέση αναμονής-αφύπνισης μεταξύ παραγωγών και καταναλωτών είναι πλέον συμμετρική Όπως μετράμε (ήδη) για τους καταναλωτές τον αριθμό των γεμάτων θέσεων της αποθήκης, έτσι πρέπει να μετράμε και για τους παραγωγούς τον αριθμό των κενών θέσεων της αποθήκης 9 lalis@inf.uth.gr

bsem mtx; /* αμοιβαίος αποκλεισμός */ gsem empty; /* # άδειων θέσεων αποθήκης */ gsem full ; /* # γεμάτων θέσεων αποθήκης */ init(mtx,1); init(full,); init(empty,n); παραγωγός: while (1) { /* produce d */ down(empty); down(mtx); put(d); up(mtx); up(full); καταναλωτής: while (1) { down(full); down(mtx); d=get(); up(mtx); up(empty); /* consume d */ 1 lalis@inf.uth.gr

Κοιμώμενος κουρέας Το κουρείο έχει ένα σαλόνι αναμονής, και ξεχωριστό δωμάτιο όπου ο κουρέας κουρεύει τους πελάτες Οι πελάτες μπαίνουν στο κουρείο από το σαλόνι, και βγαίνουν μέσα από το δωμάτιο κουρέματος Αν δεν υπάρχουν πελάτες, ο κουρέας κοιμάται Σαλόνι: αποθήκη (απεριόριστη χωρητικότητα) Κουρέας: ο (μοναδικός) καταναλωτής Πελάτες: τα δεδομένα προς κατανάλωση Λύση μόνο με δυαδικούς σηματοφόρους Ενδιαφέρει μόνο η αναμονή του κουρέα 11 lalis@inf.uth.gr

έξοδος είσοδος δωμάτιο κουρέματος σαλόνι 12 lalis@inf.uth.gr

1η προσέγγιση Ο κουρέας ελέγχει το σαλόνι, και αν υπάρχουν πελάτες, φωνάζει τον επόμενο και τον κουρεύει Αν θυμάται ότι αυτός ήταν ο τελευταίος πελάτης που είδε στο σαλόνι, κοιμάται στην καρέκλα του δωματίου αν θυμηθεί ότι όταν κούρευε τον ενόχλησε ένας πελάτης, ξυπνάει μόνος του Αν ένας πελάτης βρει άλλους πελάτες στο σαλόνι, ξέρει ότι ο κουρέας κουρεύει Αν βρει το σαλόνι άδειο, ελέγχει το δωμάτιο Αν ο κουρέας κοιμάται, τον ξυπνάει, αλλιώς ζητά συγγνώμη για την ενόχληση και γυρίζει στο σαλόνι 13 lalis@inf.uth.gr

αφύπνιση/παρενόχληση κουρέα από έναν νέο πελάτη 14 lalis@inf.uth.gr

int avl=; /* # πελατών στο σαλόνι */ bsem mtx; /* αμοιβαίος αποκλεισμός */ bsem sleep; /* αναμονή κουρέα */ init(sleep,); init(mtx,1); Customer: while (1) { down(mtx); // new customer arrives avl++; if (avl == 1) { up(sleep); up(mtx); πρώτος στο σαλόνι: ξύπνα/ενόχλησε τον κουρέα Barber: int n=; /* old avl value */ while (1) { if (n == ) { down(sleep); down(mtx); // pick next customer avl--; n = avl; up(mtx); // give haircut θυμάμαι ότι το σαλόνι ήταν άδειο: επιχειρώ να κοιμηθώ 15 lalis@inf.uth.gr

Παρατήρηση Έστω ότι οι πελάτες φτάνουν με τον ίδιο ρυθμό με τον οποίο τους κουρεύει ο κουρέας Ο εκάστοτε επόμενος πελάτης θα βρίσκει το σαλόνι πάντα άδειο, και θα ενοχλεί τον κουρέα χωρίς λόγο (αφού δεν κοιμάται) Γίνονται «άσκοπες» κλήσεις up/down στον sleep 16 lalis@inf.uth.gr

Ιδανικά Ο πελάτης ενοχλεί τον κουρέα μόνο αν αυτός όντως κοιμάται (όχι όταν κουρεύει) Η up(sleep) πρέπει να καλείται μόνο αν ο κουρέας έχει ήδη (ή πρόκειται να) καλέσει down(sleep) Ο κουρέας πρέπει να σηματοδοτεί (με ρητό τρόπο) στον πελάτη ότι πρέπει να τον ξυπνήσει 17 lalis@inf.uth.gr

2η προσέγγιση Ο κουρέας ελέγχει το σαλόνι, και αν υπάρχουν πελάτες, φωνάζει τον επόμενο και τον κουρεύει Αν δεν υπάρχουν πελάτες στο σαλόνι, κοιμάται στον καναπέ του σαλονιού (σήμα προς τον επόμενο πελάτη ότι πρέπει να τον ξυπνήσει) Αν ένας πελάτης βρει άλλους πελάτες στο σαλόνι, ξέρει ότι ο κουρέας κουρεύει Αν βρει το σαλόνι άδειο, πάλι ξέρει ότι ο κουρέας κουρεύει (οπότε δεν επιχειρεί να τον ξυπνήσει) Αν βρει τον κουρέα στον καναπέ, τον ξυπνάει 18 lalis@inf.uth.gr

αφύπνιση κουρέα από έναν νέο πελάτη 19 lalis@inf.uth.gr

int avl=; /* # πελατών στο σαλόνι, σήμα κουρέα */ bsem mtx; /* αμοιβαίος αποκλεισμός */ bsem sleep; /* αναμονή κουρέα */ init(sleep,); init(mtx,1); Customer: while (1) { down(mtx); // new customer arrives avl++; if (avl == ) { up(sleep); up(mtx); ο κουρέας σίγουρα κοιμάται: ξύπνα τον δεν υπάρχει πελάτης στο σαλόνι: πάω για ύπνο, αφήνοντας σήμα αφύπνισης στον επόμενο πελάτη Barber: while (1) { down(mtx); avl--; if (avl == -1) { up(mtx); down(sleep); down(mtx); // pick next customer up(mtx); // give haircut 2 lalis@inf.uth.gr

int avl=; /* # πελατών στο σαλόνι */ bsem mtx; /* αμοιβαίος αποκλεισμός */ bsem sleep; /* αναμονή κουρέα */ init(sleep,); init(mtx,1); Customer: while (1) { /* produce d */ down(mtx); // new customer arrives avl++; if (avl == 1) { up(sleep); up(mtx); Γιατί αυτή η λύση δεν είναι σωστή; Barber: while (1) { down(mtx); if (avl == ) { up(mtx); down(sleep); down(mtx); avl--; // pick next customer up(mtx); // give haircut 21 lalis@inf.uth.gr

int avl=; /* # πελατών στο σαλόνι, σήμα κουρέα */ bsem mtx; /* αμοιβαίος αποκλεισμός */ bsem sleep; /* αναμονή κουρέα */ init(sleep,); init(mtx,1); Customer: while { down(mtx); // new customer arrives avl++; if (avl <= ) { up(sleep); up(mtx); Είναι η λύση σωστή για πολλούς παραγωγούς; Είναι η λύση σωστή για πολλούς καταναλωτές; Barber: while (1) { down(mtx); avl--; if (avl < ) { up(mtx); down(sleep); down(mtx); // pick next customer up(mtx); // give haircut 22 lalis@inf.uth.gr

Αναγνώστες-Εγγραφείς (με σηματοφόρους) 23 lalis@inf.uth.gr

Αναγνώστες και εγγραφείς To ΚΤ προσπελάζεται είτε για την ανάγνωση είτε για την αλλαγή/γράψιμο κοινών δεδομένων Ανάγνωση Ανάγνωση: NAI Ανάγνωση Γράψιμο: OXI Γράψιμο Γράψιμο: OXI Αναγνώστης: νήμα που θέλει να διαβάσει Εγγραφέας: νήμα που θέλει να γράψει Απαιτείται διαφορετικός κώδικας εισόδου στο ΚΤ και εξόδου από το ΚΤ για αναγνώστες και εγγραφείς 24 lalis@inf.uth.gr

25 lalis@inf.uth.gr

Βασική ιδέα Η περίπτωση των εγγραφέων αντιστοιχεί ακριβώς στο «κλασικό» πρόβλημα του ΚΤ Χρησιμοποιούμε τον δυαδικό σηματοφόρο wmtx Όλοι οι αναγνώστες μαζί μπορεί να θεωρηθούν ως ένας ειδικός «σύνθετος» εγγραφέας Ο πρώτος αναγνώστης που επιχειρεί να μπει στο ΚΤ σηματοδοτεί την άφιξη του ειδικού εγγραφέα Ο τελευταίος αναγνώστης που εξέρχεται από το ΚΤ σηματοδοτεί την αναχώρηση του ειδικού εγγραφέα Χρησιμοποιούμε τον μετρητή rds για να μετράμε τους αναγνώστες, και τον δυαδικό σηματοφόρο rmtx για τον αμοιβαίο αποκλεισμό στον μετρητή rds 26 lalis@inf.uth.gr

int rds=; /* # αναγνωστών στο ΚΤ */ bsem rmtx; /* αα αναγνωστών */ bsem wmtx; /* αα εγγραφέων/αναγνωστών */ init(rmtx,1); init(wmtx,1); Writer: while (1) { down(wmtx); /* write */ up(wmtx); Reader: while (1) { down(rmtx); if (rds == ) { down(wmtx); rds++; up(rmtx); /* read */ down(rmtx); rds--; if (rds == ) { up(wmtx); up(rmtx); 27 lalis@inf.uth.gr

αρχική κατάσταση wmtx 1 ΚΤ rmtx 1 rds 28 lalis@inf.uth.gr

άφιξη αναγνώστη R1 wmtx 1 ΚΤ R1 rmtx 1 rds 29 lalis@inf.uth.gr

R1 εισέρχεται στο ΚΤ wmtx ΚΤ rmtx 1 R1 rds 1 3 lalis@inf.uth.gr

άφιξη εγγραφέα W1 wmtx ΚΤ W1 rmtx 1 R1 rds 1 31 lalis@inf.uth.gr

W1 περιμένει wmtx rmtx 1 W1 ΚΤ R1 rds 1 32 lalis@inf.uth.gr

άφιξη αναγνώστη R2 R2 wmtx rmtx 1 W1 ΚΤ R1 rds 1 33 lalis@inf.uth.gr

R2 εισέρχεται στο ΚΤ wmtx rmtx 1 W1 R2 ΚΤ R1 rds 2 34 lalis@inf.uth.gr

έξοδος αναγνώστη R2 από το ΚΤ wmtx rmtx 1 W1 ΚΤ R1 rds 1 R2 35 lalis@inf.uth.gr

έξοδος αναγνώστη R1 από το ΚΤ, και αφύπνιση του εγγραφέα W1 και... wmtx W1 ΚΤ rmtx 1 rds R1 36 lalis@inf.uth.gr

... είσοδος του εγγραφέα W1 στο ΚΤ wmtx W1 ΚΤ rmtx 1 rds 37 lalis@inf.uth.gr

... είσοδος του εγγραφέα W1 στο ΚΤ wmtx ΚΤ rmtx 1 W1 rds 38 lalis@inf.uth.gr

άφιξη αναγνώστη R3 wmtx ΚΤ R3 rmtx 1 W1 rds 39 lalis@inf.uth.gr

R3 περιμένει wmtx R3 ΚΤ rmtx W1 rds 1 4 lalis@inf.uth.gr

άφιξη αναγνώστη R4 wmtx R3 ΚΤ R4 rmtx W1 rds 1 41 lalis@inf.uth.gr

R4 περιμένει wmtx R3 ΚΤ rmtx W1 R4 rds 1 42 lalis@inf.uth.gr

άφιξη αναγνώστη R5 wmtx R3 ΚΤ R5 rmtx W1 R4 rds 1 43 lalis@inf.uth.gr

R5 περιμένει wmtx R3 ΚΤ rmtx W1 R5 R4 rds 1 44 lalis@inf.uth.gr

άφιξη εγγραφέα W2 wmtx R3 ΚΤ W2 rmtx W1 R5 R4 rds 1 45 lalis@inf.uth.gr

W2 περιμένει wmtx W2 R3 ΚΤ rmtx W1 R5 R4 rds 1 46 lalis@inf.uth.gr

έξοδος εγγραφέα W1, και αφύπνιση του αναγνώστη R3, και... wmtx W2 R3 ΚΤ rmtx R5 R4 rds 1 W1 47 lalis@inf.uth.gr

... αφύπνιση του αναγνώστη R4, είσοδος αναγνώστη R3 στο ΚΤ, και... wmtx W2 R3 ΚΤ rmtx R5 R4 rds 1 48 lalis@inf.uth.gr

... αφύπνιση του αναγνώστη R5, είσοδος αναγνώστη R4 στο ΚΤ, και... wmtx W2 ΚΤ rmtx R5 R3 R4 rds 2 49 lalis@inf.uth.gr

... είσοδος αναγνώστη R5 στο ΚΤ wmtx W2 ΚΤ rmtx 1 R4 R3 R5 rds 3 5 lalis@inf.uth.gr

άφιξη αναγνώστη R6 wmtx W2 ΚΤ R6 rmtx 1 R4 R3 R5 rds 3 51 lalis@inf.uth.gr

... που εισέρχεται στο ΚΤ wmtx W2 ΚΤ rmtx 1 R6 R4 R5 R3 rds 4 52 lalis@inf.uth.gr

... που εισέρχεται στο ΚΤ wmtx W2 ΚΤ rmtx 1 R6 R4 R5 R3 rds 4 53 lalis@inf.uth.gr

Προτεραιότητες Οι αναγνώστες έχουν προτεραιότητα εισόδου στο ΚΤ σε σχέση με τους εγγραφείς Όσο υπάρχει τουλάχιστον ένας αναγνώστης στο ΚΤ, κάθε νέος αναγνώστης εισέρχεται άμεσα στο ΚΤ, προσπερνώντας εγγραφείς που τυχόν περιμένουν (πιθανώς εδώ και πολλή ώρα) να μπουν στο ΚΤ Αντίθετα, όταν εξέρχεται ένας εγγραφέας από το ΚΤ, η σειρά πάει στο επόμενο νήμα που περιμένει (είτε εγγραφέας είτε αναγνώστης) Περίπτωση λιμοκτονίας για τους εγγραφείς Δεν υπάρχει περίπτωση λιμοκτονίας για αναγνώστες 54 lalis@inf.uth.gr

Μια πιο δίκαιη λύση Θέλουμε ένας νέος αναγνώστης να περιμένει αν υπάρχουν εγγραφείς που περιμένουν να εισέλθουν στο ΚΤ (αντί να τους προσπεράσει) Αριθμός αναγνωστών και εγγραφέων μέσα στο ΚΤ: ακέραιοι rds και wrs Ξεχωριστές ουρές αναμονής για αναγνώστες και εγγραφείς: δυαδικοί(;) σηματοφόροι rq και wq Αριθμός αναγνωστών και εγγραφέων που περιμένουν στις ουρές αναμονής: ακέραιοι rw και ww Προστασία των μετρητών ανάμεσα σε αναγνώστες και εγγραφείς: δυαδικός σηματοφόρος mtx 55 lalis@inf.uth.gr

bsem mtx; /* αα εγγραφέων/αναγνωστών */ bsem wq; gsem rq; /* ουρά αναμονής εγγραφέων/αναγνωστών */ int ww=,rw=; /* # εγγραφέων/αναγνωστών σε αναμονή */ int wrs=,rds=; /* # εγγραφέων/αναγνωστών στο ΚΤ */ init(mtx,1); init(rq,); init(wq,); Writer: down(mtx); if (rds+wrs > ) { ww++; up(mtx); down(wq); else { wrs++; up(mtx); /* write */ down(mtx); wrs--; if (rw > ) { do{ rw--; rds++; up(rq); while (rw > ); else if (ww > ) { ww--; wrs++; up(wq); up(mtx); Reader: down(mtx); if (wrs+ww > ) { rw++; up(mtx); down(rq); else { rds++; up(mtx); /* read */ down(mtx); rds--; if (rds == ) && (ww > ) { ww--; wrs++; up(wq); up(mtx); γιατί ο σηματοφόρος είναι γενικός και όχι δυαδικός; 56 lalis@inf.uth.gr

bsem mtx; /* αα εγγραφέων/αναγνωστών */ bsem wq,rq; /* ουρά αναμονής εγγραφέων/αναγνωστών */ int ww=,rw=; /* # εγγραφέων/αναγνωστών σε αναμονή */ int wrs=,rds=; /* # εγγραφέων/αναγνωστών στο ΚΤ */ init(mtx,1); init(rq,); init(wq,); Writer: Reader: down(mtx); if (rds+wrs > ) { ww++; up(mtx); down(wq); else { wrs++; up(mtx); /* write */ down(mtx); wrs--; if (rw > ) { rw--; rds++; up(rq); else if (ww > ) { ww--; wrs++; up(wq); up(mtx); down(mtx); if (wrs+ww > ) { rw++; up(mtx); down(rq); if (rw > ) { rw--; rds++; up(rq); else { rds++; up(mtx); /* read */ down(mtx); rds--; if (rds == ) && (ww > ) { ww--; wrs++; up(wq); up(mtx); είναι η λύση σωστή; 57 lalis@inf.uth.gr

bsem mtx; /* αα εγγραφέων/αναγνωστών */ bsem wq,rq; /* ουρά αναμονής εγγραφέων/αναγνωστών */ int ww=,rw=; /* # εγγραφέων/αναγνωστών σε αναμονή */ int wrs=,rds=; /* # εγγραφέων/αναγνωστών στο ΚΤ */ init(mtx,1); init(rq,); init(wq,); Writer: down(mtx); if (rds+wrs > ) { ww++; up(mtx); down(wq); else { wrs++; up(mtx); /* write */ down(mtx); wrs--; if (rw > ) { rw--; rds++; up(rq); else { if (ww > ) { ww--; wrs++; up(wq); up(mtx); Reader: down(mtx); if (wrs+ww > ) { rw++; up(mtx); down(rq); if (rw > ) { rw--; rds++; up(rq); else { up(mtx); else { rds++; up(mtx); /* read */ down(mtx); rds--; if (rds == ) && (ww > ) { ww--; wrs++; up(wq); up(mtx); 58 lalis@inf.uth.gr

Συνδαιτυμόνες Φιλόσοφοι (με σηματοφόρους) 59 lalis@inf.uth.gr

Οι συνδαιτυμόνες φιλόσοφοι Η ζωή ενός φιλόσοφου: σκέφτομαι, πεινάω, τρώω Υπάρχουν άπλετα μακαρόνια πάνω σε ένα κοινό τραπέζι, όπου κάθε φιλόσοφος έχει την θέση του Για να μπορέσει να φάει ένας φιλόσοφος, πρέπει να πιάσει τα δύο πιρούνια που είναι δεξιά και αριστερά από την θέση του 6 lalis@inf.uth.gr

think (hard) grab forks eat (a lot) Pi 61 lalis@inf.uth.gr

Προσέγγιση Όταν ο i-οστός φιλόσοφος πεινάσει, επιχειρεί να πιάσει πρώτα το πιρούνι στα δεξιά του RIGHT(i), και μετά το πιρούνι στα αριστερά του LEFT(i) Αφού φάει, αφήνει τα δύο πιρούνια πάνω στο τραπέζι Κάθε πιρούνι αποτελεί ένα ξεχωριστό ΚΤ ανάμεσα στους δύο φιλόσοφους που κάθονται σε γειτονικές θέσεις στο τραπέζι Κάθε πιρούνι: ένας δυαδικός σηματοφόρος fork[i] Φιλόσοφος επιχειρεί να πιάσει το πιρούνι: down Φιλόσοφος αφήνει κάτω ένα πιρούνι: up 62 lalis@inf.uth.gr

bsem fork[n]; for (i=; i<n; i++) { init(fork[i],1); Philosopher i: while (1) { /* think */ down(fork[right(i)]); down(fork[left(i)]); /* eat */ up(fork[right(i)]); up(fork[left(i)]); 63 lalis@inf.uth.gr

Η λύση δεν είναι σωστή Υπάρχει πιθανότητα αδιεξόδου Αν όλοι οι φιλόσοφοι πεινάσουν και καθίσουν στο τραπέζι την ίδια στιγμή όλοι θα πιάσουν το ξυλάκι στα δεξιά τους στη συνέχεια, κανείς δεν θα βρει ελεύθερο το ξυλάκι στα αριστερά του Λύση Α δεν επιτρέπουμε σε περισσότερους από Ν-1 φιλόσοφους να έχουν πρόσβαση στο τραπέζι Λύση Β υποχρεώνουμε έναν φιλόσοφο (π.χ. Ν-1) να πιάνει πρώτα το αριστερό και μετά το δεξί ξυλάκι (σπάσιμο συμμετρίας) μια άλλη οπτική γωνία: οι φιλόσοφοι πρέπει να επιχειρούν να πιάνουν τα ξυλάκια με αύξουσα αριθμητική σειρά 64 lalis@inf.uth.gr

bsem fork[n]; for (i=; i<n; i++) { init(fork[i],1); gsem table; init(table,n-1); Philosopher i: while (1) { /* think */ down(table); down(fork[right(i)]); down(fork[left(i)]); /* eat */ up(fork[right(i)]); up(fork[left(i)]); up(table); 65 lalis@inf.uth.gr

bsem fork[n]; for (i=; i<n; i++) { init(fork[i],1); Philosopher i: while (1) { /* think */ if (i!= N-1) { down(fork[right(i)]); down(fork[left(i)]); else { down(fork[left(i)]); down(fork[right(i)]); /* eat */ up(fork[right(i)]); up(fork[left(i)]); 66 lalis@inf.uth.gr

Μια διαφορετική προσέγγιση Ρητή πληροφορία κατάστασης για κάθε φιλόσοφο THINKING: δεν ενδιαφέρεται να φάει HUNGRY: περιμένει να φάει EATING: τρώει Χρησιμοποιείται ώστε ένας φιλόσοφος να αποφασίσει (1) αν μπορεί να φάει, και (2) αφού φάει, αν πρέπει να ξυπνήσει κάποιον από τους γείτονες του Κάθε φιλόσοφος έχει την δική του ουρά αναμονής: δυαδικός σηματοφόρος wait[i] Οι κοινές μεταβλητές κατάστασης προστατεύονται μέσω ενός ξεχωριστού δυαδικού σηματοφόρου mtx 67 lalis@inf.uth.gr

bsem mtx,wait[n]; init(mtx,1); for (i=; i<n; i++) { init(wait[i],); int state[n] = {THINKING,,THINKING; while (1) { /* thinking */ down(mtx); state[i] = HUNGRY; test(i); /* see if I can eat */ up(mtx); down(wait[i]); /* wait, if I cannot eat */ /* eating */ down(mtx); state = THINKING; test(right(i)); /* allow for right neighbor to eat */ test(left(i)); /* allow for left neighbor to eat */ up(mtx); είναι η λύση σωστή; void test(int i) { if ( (state[i]==hungry) && (state[left(i)]!=eating) && (state[right(i)]!=eating)) { state[i] = EATING; up(wait[i]); 68 lalis@inf.uth.gr

Γενική μοντελοποίηση αδιεξόδου Ν διεργασίες, Μ πόροι Για να λάβει μια διεργασία ένα πόρο R, αυτός δεν πρέπει ήδη να χρησιμοποιείται από άλλη διεργασία Όταν μια διεργασία έναν πόρο, περιμένει μέχρι να λάβει άδεια να τον χρησιμοποιήσει δεν μπορεί να «οπισθοδρομήσει» ή να απελευθερώσει τους πόρους που ίσως ήδη κρατά η ίδια Αδιέξοδο: κατάσταση «κυκλικής» αναμονής όπου κάθε διεργασία περιμένει να ελευθερωθεί ένας πόρος που έχει δεσμεύσει μια άλλη διεργασία, που με την σειρά της περιμένει... Μια ειδική περίπτωση ομαδικής λιμοκτονίας 69 lalis@inf.uth.gr

used by P1 waiting for Resource D Resource Α P4 P2 Resource C Resource Β P3 7 lalis@inf.uth.gr

Αντιμετώπιση αδιεξόδου Αποφυγή αδιεξόδου Είμαστε «συντηρητικοί», φροντίζουμε να μην υπάρχει περίπτωση δημιουργίας αδιεξόδου Σχεδιάζουμε την πρόσβαση στους κοινούς πόρους με κατάλληλο τρόπο, π.χ. δέσμευση με αύξουσα σειρά Εντοπισμός & επίλυση αδιεξόδου Είμαστε «αισιόδοξοι», αφήνουμε τις διεργασίες να επιχειρούν δέσμευση των πόρων κατά βούληση, ελπίζοντας ότι δεν θα δημιουργηθεί αδιέξοδο Υλοποιούμε μηχανισμό εντοπισμού αδιεξόδου, και τερματισμού / οπισθοδρόμησης διεργασιών (όμως αυτό δεν είναι πάντα εφικτό / πρακτικό) 71 lalis@inf.uth.gr