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

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

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

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

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

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

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

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

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

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

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Διάλεξη Εισαγωγή στη Java, Μέρος Γ

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

Εισαγωγικά & Βασικές Έννοιες

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

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

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

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

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Αντικειμενοστρεφής Προγραμματισμός

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

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

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

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

Συλλογές, Στοίβες και Ουρές

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

Οντοκεντρικός Προγραμματισμός

Δομές Δεδομένων & Ανάλυση Αλγορίθμων. 3ο Εξάμηνο. Ουρά (Queue) Υλοποίηση της με τη βοήθεια πίνακα.

Προγραμματισμός Ι (ΗΥ120)

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

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

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

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

Το παρακάτω πρόγραμμα ορίζει δυο κλάσεις την SimpleThread και την TwoThreadsTest:

Τ.Ε.Ι. Μεσολογγίου, Τµήµα τηλεπικοινωνιακών Συστημάτων & Δικτύων

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

Δείκτες σε συναρτήσεις. Προγραμματισμός II 1

ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 11/3/2008

ΕΝΟΤΗΤΑ 4 Λήψη Αποφάσεων και Συναρτήσεις Ελέγχου

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ. Δομές Δεδομένων. Ιωάννης Γ. Τόλλης Τμήμα Επιστήμης Υπολογιστών Πανεπιστήμιο Κρήτης

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

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

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

CSLab National Technical University of Athens

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ. Δομές Δεδομένων. Ιωάννης Γ. Τόλλης Τμήμα Επιστήμης Υπολογιστών Πανεπιστήμιο Κρήτης

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα με πίνακες. Constructors. Υλοποίηση Στοίβας

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

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Εισαγωγή στη Java

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

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Εισαγωγή στη Java II

Ανάπτυξη και Σχεδίαση Λογισμικού

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ & ΥΠΟΛΟΓΙΣΤΙΚΗ ΦΥΣΙΚΗ

Συγχρονισμός Μέρος Α : Κρίσιμο τμήμα και κλειδώματα

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

Εισαγωγή στον Αντικειμενοστρεφή Προγραμματισμό Διάλεξη #2

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

Βασικές Έννοιες Πρ Ταο υγρ τόα χ μ ρ μ ο α ν τισμ ος Π ό ρ ςο ΙΙΙ γραμματισμός 1

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

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

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

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

Αντικειμενοστρεφής Προγραμματισμός

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

Δοµές Δεδοµένων. 6η Διάλεξη Αναδροµικές Εξισώσεις και Αφηρηµένοι Τύποι Δεδοµένων. Ε. Μαρκάκης

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

Εισαγωγικά & Βασικές Έννοιες

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

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Αναφορές

Προγραμματισμός Ταυτόχρονος Προγραμματισμός

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

Διδάσκων: Παναγιώτης Ανδρέου

Δομές ελέγχου ροής προγράμματος

Εισαγωγή στον Προγραµµατισµό, Αντώνιος Συµβώνης, ΣΕΜΦΕ, ΕΜΠ,, Slide 6

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

Μηχανισμοί και προγραμματιστικές δομές συγχρονισμού. Προβλήματα συγχρονισμού (και λύσεις)

Ανάπτυξη και Σχεδίαση Λογισμικού

Transcript:

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

Σηματοφόροι Οι σηματοφόροι είναι ένας ΑΤΔ με συγκεκριμένες λειτουργίες πρόσβασης Μπορεί να υλοποιηθούν εύκολα με τον μηχανισμό του ελεγκτή Ο αμοιβαίος αποκλεισμός κατά την πρόσβαση του εσωτερικού μετρητή επιτυγχάνεται αυτόματα, λόγω του μηχανισμού του ελεγκτή Το πρόβλημα που πρέπει να λυθεί είναι η αναμονή μέσα στην down, για το οποίο χρησιμοποιούμε μια μεταβλητή συνθήκης Ταυτόχρονος Προγραμματισμός 2 lalis@inf.uth.gr

monitor bsem { bit val; /* τιμή σηματοφόρου */ condition q; /* ουρά αναμονής */ void init(bit v) { val = v; void down() { if (val == 0) { wait(q); val = 0; void up() { val = 1; signal(q); Ταυτόχρονος Προγραμματισμός 3 lalis@inf.uth.gr

monitor bsem { bit val; /* τιμή σηματοφόρου */ condition q; /* ουρά αναμονής */ void init(bit v) { val = v; είναι σωστό για μοντέλο open; void down() { if (val == 0) { wait(q); val = 0; void up() { val = 1; signal(q); Ταυτόχρονος Προγραμματισμός 4 lalis@inf.uth.gr

monitor bsem { bit val; /* τιμή σηματοφόρου */ condition q; /* ουρά αναμονής */ void init(bit v) { val = v; είναι σωστό για μοντέλο open; void down() { while (val == 0) { wait(q); val = 0; void up() { val = 1; signal(q); Ταυτόχρονος Προγραμματισμός 5 lalis@inf.uth.gr

monitor bsem { int val; /* τιμή σηματοφόρου */ condition q; /* ουρά αναμονής */ void init(int v) { val = v; τεχνική «κοιμώμενου κουρέα» void down() { val--; if (val < 0) { wait(q); void up() { if (val < 1) { val++; if (val <= 0) { signal(q); Ταυτόχρονος Προγραμματισμός 6 lalis@inf.uth.gr

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

monitor buf { void init(); void put(data d); Data void get(); Producer: while (1) {... /* produce Data item d */ put(d); Consumer: while (1) {... d=get(); /* consume Data item d */...... Ταυτόχρονος Προγραμματισμός 8 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int avl; /* # γεμάτων θέσεων */ condition notempty; /* αναμονή καταναλωτή */ void init() {... /* αρχικοποίηση αποθήκης */ avl = 0; void put(data d) {... /* τοποθέτηση στοιχείου στην αποθήκη */ avl++; if (avl == 1) { signal(notempty); Data get() { if (avl == 0) { wait(notempty); avl--;... /* απομάκρυση στοιχείου από την αποθήκη */ return(...); Ταυτόχρονος Προγραμματισμός 9 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int avl; /* # γεμάτων θέσεων */ condition notempty; /* αναμονή καταναλωτή */ void init() {... /* αρχικοποίηση αποθήκης */ avl = 0; είναι σωστό για μοντέλο open; void put(data d) {... /* τοποθέτηση στοιχείου στην αποθήκη */ avl++; if (avl == 1) { signal(notempty); Data get() { if (avl == 0) { wait(notempty); avl--;... /* απομάκρυση στοιχείου από την αποθήκη */ return(...); Ταυτόχρονος Προγραμματισμός 10 lalis@inf.uth.gr

Μοντέλο open Ο καταναλωτής ελέγχει την αποθήκη και μπλοκάρει αν αυτή είναι άδεια μια μοναδική φορά Όμως, όταν καλείται η signal, ο έλεγχος δεν δίνεται απαραίτητα στον καταναλωτή που περίμενε Μπορεί να δοθεί σε έναν άλλο καταναλωτή, που έχει μπλοκάρει προσπαθώντας να καλέσει την get, και έτσι να προσπεραστεί ο πρώτος καταναλωτής Η συνθήκη αφύπνισης μπορεί να ακυρωθεί Η συνθήκη αναμονής πρέπει να ελέγχεται ξανά, αφού ο καταναλωτής εκτελέσει / βγει από την wait Ταυτόχρονος Προγραμματισμός 11 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int avl; /* # γεμάτων θέσεων */ condition notempty; /* αναμονή καταναλωτή */ void init() {... /* αρχικοποίηση αποθήκης */ avl = 0; είναι σωστό για μοντέλο open; void put(data *d) {... /* τοποθέτηση στοιχείου στην αποθήκη */ avl++; if (avl == 1) { signal(notempty); Data *get() { while (avl == 0) { wait(notempty); avl--;... /* απομάκρυνση στοιχείου από την αποθήκη */ return(...); Ταυτόχρονος Προγραμματισμός 12 lalis@inf.uth.gr

Διάφορα προβλήματα Δεν γνωρίζουμε πότε ακριβώς πρέπει να αφυπνιστεί ένας καταναλωτής μέσω signal(notempty) Υπάρχει περίπτωση να κληθεί signal(notempty) χωρίς να περιμένει κάποιος καταναλωτής Χειρότερα, υπάρχει περίπτωση να μην κληθεί signal(notempty) παρότι κάποιος καταναλωτής περιμένει Υπάρχει και το «γνωστό» πρόβλημα λιμοκτονίας, καθώς ένας καταναλωτής μπορεί να προσπερνιέται συνεχώς από νέους καταναλωτές Λύση: τεχνική κοιμώμενου κουρέα Ταυτόχρονος Προγραμματισμός 13 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int avl; /* # γεμάτων θέσεων */ condition notempty; /* αναμονή καταναλωτή */ void init() {... /* αρχικοποίηση αποθήκης */ avl = 0; void put(data *d) {... /* τοποθέτηση στοιχείου στην αποθήκη */ avl++; if (avl <= 0) { signal(notempty); Data *get() { avl--; if (avl < 0) { wait(notempty);... /* απομάκρυνση στοιχείου από την αποθήκη */ return(...); Ταυτόχρονος Προγραμματισμός 14 lalis@inf.uth.gr

Παραγωγός-καταναλωτής με αποθήκη περιορισμένης χωρητικότητας Η σχέση αναμονής/αφύπνισης είναι συμμετρική ανάμεσα στους καταναλωτές και τους παραγωγούς Ότι κάναμε για την αναμονή των καταναλωτών (σε άδεια αποθήκη) και την αφύπνιση τους από τους παραγωγούς, το ίδιο πρέπει να γίνει και για την αναμονή παραγωγών (σε γεμάτη αποθήκη) και την αφύπνιση τους από τους καταναλωτές Στο ίδιο πνεύμα με την προηγούμενη λύση Ταυτόχρονος Προγραμματισμός 15 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int free,full; /* # άδειων/γεμάτων θέσεων */ condition notfull,notempty; /* αναμονή παρ. & κατ. */ void init() {... /* αρχικοποίηση αποθήκης */ free = N; full = 0; void put(data *d) { if (free == 0) { wait(notfull); free--;... /* τοποθέτηση στοιχείου στην αποθήκη */ full++; if (full == 1) { signal(notempty); Data *get() { Data *d; if (full == 0) { wait(notempty); full--;... /* απομάκρυση στοιχείου από την αποθήκη */ free++; if (free == 1) { signal(notfull); return(...); Ταυτόχρονος Προγραμματισμός 16 lalis@inf.uth.gr

monitor buf {... /* μεταβλητές αποθήκης */ int free,full; /* # άδειων/γεμάτων θέσεων */ condition notfull,notempty; /* αναμονή παρ. & κατ. */ void init() {... /* αρχικοποίηση αποθήκης */ free = N; full = 0; void put(data *d) { free--; if (free < 0) { wait(notfull);... /* τοποθέτηση στοιχείου στην αποθήκη */ full++; if (full <= 0) { signal(notempty); Data *get() { Data *d; full--; if (full < 0) { wait(notempty);... /* απομάκρυση στοιχείου από την αποθήκη */ free++; if (free <= 0) { signal(notfull); return(...); Ταυτόχρονος Προγραμματισμός 17 lalis@inf.uth.gr

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

monitor rwsync { void init(); void startread(); void stopread(); void startwrite(); void stopwrite(); Reader: while (1) { startread(); /* read */ stopread(); Writer: while (1) { startwrite(); /* write */ stopwrite(); Ταυτόχρονος Προγραμματισμός 19 lalis@inf.uth.gr

monitor rwsync { int rds,wrs; /* #αναγνωστών/εγγραφέων στο ΚΤ */ condition rq,wq; /* ουρές αναμονής */ int rcnt, wcnt; /* #νημάτων μπλοκαρισμένα σε rq/wq */ void init() { rds = 0; wrs = 0; rcnt = 0; wcnt =0; void startread(); void stopread(); void startwrite(); void stopwrite(); Ταυτόχρονος Προγραμματισμός 20 lalis@inf.uth.gr

void startread() { if (wrs > 0) { rcnt++; wait(rq); rds++; void stopread() { rds--; if ((rds == 0) && (wcnt > 0)) { wcnt--; signal(wq); void startwrite() { if ((wrs > 0) (rds > 0)) { wcnt++; wait(wq); wrs++; void stopwrite() { wrs--; if (rcnt > 0) { do { rcnt--; signal(rq); while (rcnt > 0); else if (wcnt > 0) { wcnt--; signal(wq); Ταυτόχρονος Προγραμματισμός 21 lalis@inf.uth.gr

void startread() { if (wrs > 0) { rcnt++; wait(rq); if (rcnt > 0) { rcnt--; signal(rq); rds++; void stopread() { rds--; if ((rds == 0) && (wcnt > 0)) { wcnt--; signal(wq); void startwrite() { if ((wrs > 0) (rds > 0)) { wcnt++; wait(wq); wrs++; void stopwrite() { wrs--; if (rcnt > 0) { rcnt--; signal(rq); else if (wcnt > 0) { wcnt--; signal(wq); Ταυτόχρονος Προγραμματισμός 22 lalis@inf.uth.gr

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

void startread() { if ((wrs > 0) (wcnt > 0)) { rcnt++; wait(rq); if (rcnt > 0) { rcnt--; signal(rq); rds++; void stopread() { rds--; if ((rds == 0) && (wcnt > 0)) { wcnt--; signal(wq); void startwrite() { if ((wrs > 0) (rds > 0)) { wcnt++; wait(wq); wrs++; void stopwrite() { wrs--; if (rcnt > 0) { rcnt--; signal(rq); else if (wcnt > 0) { wcnt--; signal(wq); Ταυτόχρονος Προγραμματισμός 24 lalis@inf.uth.gr

Προσπεράσματα Πάλι μπορεί να προσπεραστεί ένας εγγραφέας Όταν εξέρχεται ένας εγγραφέας από το ΚΤ, δίνει προτεραιότητα στους αναγνώστες, που αφυπνίζονται όλοι Ένας αναγνώστης που έφτασε την χρονική στιγμή t1 μπορεί να προσπεράσει έναν εγγραφέα που έφτασε την χρονική στιγμή t2 Όμως, δεν μπορεί να υπάρξει λιμοκτονία γιατί; Επίσης, η προτεραιότητα μπορεί να δοθεί στους εγγραφείς αλλά τότε υπάρχει περίπτωση λιμοκτονίας για τους αναγνώστες Ταυτόχρονος Προγραμματισμός 25 lalis@inf.uth.gr

Συνδαιτημόνες φιλόσοφοι ιδέα Υλοποιούμε τη ρουτίνα getforks(i) μέσω της οποίας ο i-οστός φιλόσοφος επιχειρεί να πιάσει τα πιρούνια που βρίσκονται δεξιά και αριστερά του Υλοποιούμε τη ρουτίνα putforks(i) μέσω της οποίας ο i-οστός φιλόσοφος αφήνει τα πιρούνια του Χρησιμοποιούμε ένα πίνακα avl[ν] που καταγράφει τα διαθέσιμα πιρούνια για κάθε φιλόσοφο (0, 1, 2) Χρησιμοποιούμε ένα πίνακα caneat[ν] από μεταβλητές συνθήκης, μια για κάθε φιλόσοφο Ταυτόχρονος Προγραμματισμός 26 lalis@inf.uth.gr

monitor table { Pi: while (1) { /* think */ void init(); void getforks(int i); void putforks (int i); getforks(i); /* eat */ putforks(i); Ταυτόχρονος Προγραμματισμός 27 lalis@inf.uth.gr

monitor dining_philosophers { int avl[n]; condition caneat[ν]; void init() { int i; for (i=0; i<ν; i++) { avl[i] = 2; void getforks(int i) { if (avl[i]!= 2) { wait(caneat[i]); avl[right(i)]--; avl[left(i)]--; void putforks(int i) { avl[right(i)]++; if (avl[right(i)] == 2) { signal(caneat[right(i)]); avl[left(i)]++; if (avl[left(i)] == 2) { signal(caneat[left(i)]); Ταυτόχρονος Προγραμματισμός 28 lalis@inf.uth.gr

Παρατηρήσεις Ο αμοιβαίος αποκλεισμός είναι εγγυημένος Δεν υπάρχει περίπτωση αδιεξόδου, και πάντα κάποιος φιλόσοφος θα καταφέρνει να τρώει Υπάρχει όμως περίπτωση λιμοκτονίας Ένας φιλόσοφος δεν θα καταφέρει να φάει ποτέ, αν οι γείτονες του τρώνε συντονισμένα εναλλάξ έτσι ώστε ποτέ να μην είναι ταυτόχρονα διαθέσιμα τόσο το δεξί όσο και το αριστερό πιρούνι του Υπάρχει θέμα signal&block ή signal&continue; Είναι η λύση σωστή για μοντέλο open; Ταυτόχρονος Προγραμματισμός 29 lalis@inf.uth.gr

Υλοποίηση ελεγκτή με σηματοφόρους (eggshell-signal&block) Ταυτόχρονος Προγραμματισμός 30 lalis@inf.uth.gr

Πρόβλημα Έστω ότι μας δίνονται σηματοφόροι Μπορούμε να πετύχουμε λειτουργικότητα συγχρονισμού στο πνεύμα ενός ελεγκτή; Ζητούμενο 1 ο : Πως επιτυγχάνεται το πλαίσιο του αμοιβαίου αποκλεισμού; Ζητούμενο 2 ο : Πως υλοποιείται μια μεταβλητή συνθήκης, καθώς και οι λειτουργίες wait / signal; Ταυτόχρονος Προγραμματισμός 31 lalis@inf.uth.gr

Eggshell mtx ουρά εισόδου x_q ουρά νημάτων που έχουν καλέσει την wait στη μεταβλητή συνθήκης x s_q νήμα που εκτελεί κώδικα του ελεγκτή ουρά νημάτων που περιμένουν (λόγω κλήσης της signal) να ελευθερωθεί ο ελεγκτής Ταυτόχρονος Προγραμματισμός 32 lalis@inf.uth.gr

Μεταβλητές πλαισίου συγχρονισμού Σηματοφόρος για αμοιβαίο αποκλεισμό: bsem mtx; /* αμοιβαίος αποκλεισμός */ init(&mtx,1); Για κάθε μεταβλητή συνθήκης x, σηματοφόρος και μετρητής για την υλοποίηση της ουράς αναμονής: bsem x_q; /* ουρά μεταβλητής συνθήκης */ int x_n=0; /* # νημάτων στην ουρά */ init(&x_q,0); x_n = 0; Σηματοφόρος και μετρητής για τις διεργασίες που μπλοκάρουν λόγω κλήσης της signal: bsem s_q; /* ουρά για signal */ int s_n; /* # νημάτων στην ουρά */ init(&s_q,0); s_n = 0; Ταυτόχρονος Προγραμματισμός 33 lalis@inf.uth.gr

void proc( ) { down(mtx); /* συμβατικός κώδικας της ρουτίνας */ if (s_n > 0) { s_n--; up(s_q); else { up(mtx); void wait(condition x) { x_n++; if (s_n > 0) { s_n--; up(s_q); else { up(mtx); down(x_q); void signal(condition x) { if (x_n > 0) { s_n++; x_n--; up(x_q); down(s_q); Ταυτόχρονος Προγραμματισμός 34 lalis@inf.uth.gr

Μια λύση αποκλειστικά για signal&exit Έστω ότι η signal καλείται μόνο ως τελευταία εντολή μιας λειτουργίας του ελεγκτή (ή τερματίζει άμεσα την λειτουργία, στο πνεύμα της exit/return) Σε αυτή τη περίπτωση, δεν χρειάζεται να μπλοκάρει το νήμα που καλεί την signal αφού στην συνέχεια θα εγκαταλείψει, εγγυημένα, τον ελεγκτή Συνεπώς δεν χρειάζεται η ουρά που υλοποιείται μέσω του σηματοφόρου s_q και μετρητή s_n Ταυτόχρονος Προγραμματισμός 35 lalis@inf.uth.gr

void proc( ) { down(mtx); /* */ up(mtx); void wait(condition x) { x_n++; up(mtx); down(x_q); void signal(condition x) { if (x_n > 0) { x_n--; up(x_q); else { up(mtx); Ταυτόχρονος Προγραμματισμός 36 lalis@inf.uth.gr

Ελεγκτές και σχεδίαση λογισμικού Ταυτόχρονος Προγραμματισμός 37 lalis@inf.uth.gr

Οι ελεγκτές δεν είναι πανάκεια Όπως κάθε εργαλείο/μηχανισμός συγχρονισμού, χρειάζεται προσοχή για να αποφεύγονται λάθη Πολλές φορές, τα λάθη δεν είναι προφανή Κλασικό πρόβλημα: αδιέξοδα (deadlocks) Ιδίως σε αντικειμενοστραφή περιβάλλοντα (όπου η ροή εκτέλεσης δεν είναι ορατή εκ των προτέρων) Nesting problem: Σύνθεση πολύπλοκων τμημάτων λογισμικού από πιο απλά τμήματα/συστατικά Reentrancy problem: Επαναφορά, με έμμεσο τρόπο, πίσω στο ίδιο πλαίσιο συγχρονισμού Ταυτόχρονος Προγραμματισμός 38 lalis@inf.uth.gr

Monitor B Monitor C Monitor A Ταυτόχρονος Προγραμματισμός 39 lalis@inf.uth.gr

class Semaphore { private int val; Semaphore(int val) { this.val = val; synchronized public void down() throws InterruptedException { while (val == 0) { wait(); val--; synchronized public void up() { val++; notify(); Ταυτόχρονος Προγραμματισμός 40 lalis@inf.uth.gr

class SafeBuffer { Object[] buf; int in, out, n; Semaphore full, empty; SafeBuffer(int size) { in=0; out=0; n=size; buf=new Object[n]; full=new Semaphore(0); empty=new Semaphore(n); synchronized public void put(object o) throws InterruptedException { empty.down(); buf[in]=o; in=(in+1)%n; full.up(); προβληματικό synchronized public Object get() throws InterruptedException { Object o; full.down(); o=buf[out]; out=(out+1)%n; empty.up(); return(o); Ταυτόχρονος Προγραμματισμός 41 lalis@inf.uth.gr

class SafeBuffer2 { Object[] buf; int in, out, n; Semaphore full, empty; SafeBuffer2(int size) { in=0; out=0; n=size; buf=new Object[n]; full=new Semaphore(0); empty=new Semaphore(n); public void put(object o) throws InterruptedException { empty.down(); synchronized(this) { buf[in]=o; in=(in+1)%n; full.up(); public Object get() throws InterruptedException { Object o; full.down(); synchronized(this) { o=buf[out]; out=(out+1)%n; empty.up(); return(o); Ταυτόχρονος Προγραμματισμός 42 lalis@inf.uth.gr

code Monitor function pointer Ταυτόχρονος Προγραμματισμός 43 lalis@inf.uth.gr

private int myval; private Listener[] mylisteners; public synchronized void addlistener(listener l) { public synchronized void rmvlistener(listener l) { public synchronized void setvalue(int val) { myval = val; for (int i = 0; i < mylisteners.length; i++) { mylisteners[i].valuechanged(val); προβληματικό Ταυτόχρονος Προγραμματισμός 44 lalis@inf.uth.gr

private int myval; private Listener[] mylisteners; public synchronized void addlistener(listener l) { public synchronized void rmvlistener(listener l) { public void setvalue(int val) { synchronized (this) { myval = val; listeners = mylisteners.clone(); προβληματικό for (int i = 0; i < listeners.length; i++) { listeners[i].valuechanged(val); Ταυτόχρονος Προγραμματισμός 45 lalis@inf.uth.gr