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

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

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

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

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

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

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

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

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

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

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

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

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

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Λιβανός Γιώργος Εξάμηνο 2017Β

Αδιέξοδα (Deadlocks)

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

Τι είναι ένα λειτουργικό σύστημα (ΛΣ); Μια άλλη απεικόνιση. Το Λειτουργικό Σύστημα ως μέρος του υπολογιστή

Λειτουργικά Συστήματα (διαχείριση επεξεργαστή, μνήμης και Ε/Ε)

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

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

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

Ιδιοκτησία Αντικειµένου

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

Το μάθημα. Λειτουργικά Συστήματα Πραγματικού Χρόνου Βασικές Έννοιες 6. Ενσωματωμένα Συστήματα (embedded systems) Παραδείγματα

Κεφάλαιο 4 Σημασιολογία μιας Απλής Προστακτικής Γλώσσας

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

ΚΕΦΑΛΑΙΟ 9. Ταυτόχρονος προγραμματισμός και νήματα. 9.1 Εισαγωγή

Συνεπής παρατήρηση εκτέλεσης & συνεπείς καθολικές καταστάσεις. Κατανεμημένα Συστήματα 1

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

Συνέπεια μνήμης σε πολυπύρηνα/πολυεπεξεργαστικά συστήματα

Θοδωρής Ανδρόνικος Τμήμα Πληροφορικής, Ιόνιο Πανεπιστήμιο

Υ- 07 Παράλληλα Συστήματα Συνέπεια και συνοχή μνήμης

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

ΧΡΟΝΟΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Συνεπείς καθολικές καταστάσεις & επιβεβαίωση ιδιοτήτων. Κατανεμημένα Συστήματα 1

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

Κεφάλαιο 4 Διεργασίες Β Τάξη ΕΠΑΛ

Λειτουργικά Συστήματα. Τ.Ε.Ι. Ιονίων Νήσων Σχολή Διοίκησης και Οικονομίας - Λευκάδα

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

Προσπέλαση κοινών πόρων Πρωτόκολλα ελέγχου αμοιβαίου αποκλεισμού

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

Λειτουργικά συστήματα πραγματικού χρόνου

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

Λειτουργικά Συστήματα Πραγματικού Χρόνου

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

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

Έλεγχος συγχρονικότητας Μέρος 1 Βάσεις Δεδομένων Διδάσκων: Μαρία Χαλκίδη

Τυχαίοι αριθμοί ρίξε μια «ζαριά»

Προβλήματα, αλγόριθμοι, ψευδοκώδικας

Mπαρμπούτι. Ενδεικτικές Απαντήσεις Φύλλου Εργασίας. Τυχαιότητα

Βασικές έννοιες. Κατανεμημένα Συστήματα 1

Κεφάλαιο 3. Διδακτικοί Στόχοι

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

Οργάνωση επεξεργαστή (2 ο μέρος) ΜΥΥ-106 Εισαγωγή στους Η/Υ και στην Πληροφορική

Υ- 01 Αρχιτεκτονική Υπολογιστών Back- end: χρονοπρογραμματισμός, εντολές προσπέλασης μνήμης

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

ΧΡΟΝΟΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

ΕισαγωγήστουςΗ/Υ. PHP Hypertext Preprocessor

Αλγόριθμος. Αλγόριθμο ονομάζουμε τη σαφή και ακριβή περιγραφή μιας σειράς ξεχωριστών οδηγιών βημάτων με σκοπό την επίλυση ενός προβλήματος.

ΧΡΟΝΟΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 6/12/07

ΛΥΜΕΝΑ ΠΡΟΒΛΗΜΑΤΑ. Γράψτε τις επόμενες διαδικασίες σε όποια γλώσσα προγραμματισμού προτιμάτε:

Βασικές έννοιες. Κατανεμημένα Συστήματα 1

Πανεπιστήμιο Θεσσαλίας Τμήμα Ηλεκτρολόγων Μηχανικών & Μηχανικών Υπολογιστών Τμήμα Πληροφορικής

Διαδικασιακός Προγραμματισμός

for for for for( . */

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

Ένα αφαιρετικό πραγματικού χρόνου μοντέλο λειτουργικού συστήματος για MPSoC

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

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

ILP (integer linear programming) βασιζόμενη εξαρτώμενη από τους πόρους μεταγλώττιση

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

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

Διάλεξη 04: Παραδείγματα Ανάλυσης

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

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

ιεργασίες και νήµατα Προγραµµατισµός ΙΙΙ 1 lalis@inf.uth.gr

Διάλεξη 04: Παραδείγματα Ανάλυσης Πολυπλοκότητας/Ανάλυση Αναδρομικών Αλγόριθμων

Transcript:

Αμοιβαίος αποκλεισμός με κοινή μνήμη 1 lalis@inf.uth.gr

Το πρόβλημα Έστω ότι δύο η περισσότερα νήματα επιθυμούν να προσπελάσουν έναν κοινό πόρο, που όμως δεν μπορεί να χρησιμοποιηθεί ταυτόχρονα Η χρήση του πόρου πρέπει να γίνει με κατάλληλο συντονισμό ανάμεσα στα νήματα Η πλέον κλασική περίπτωση: ταυτόχρονη πρόσβαση νημάτων σε κοινή μνήμη (μπορεί να προκύψουν συνθήκες ανταγωνισμού) 2 lalis@inf.uth.gr

3 lalis@inf.uth.gr

Παράδειγμα: κοινή μεταβλητή int i=0; P1: i=i+1 P2: i=i+1 tmp1=i i=tmp1+1 tmp2=i i=tmp2+1 Οι εντολές του ενός νήματος πιθανώς να μην εκτελεστούν συνεχόμενα, χωρίς να μεσολαβήσει ανταγωνιστική εντολή του άλλου νήματος Μπορεί να προκύψει «ασυνέπεια» ως προς την τιμή που θα λάβει η κοινή μεταβλητή i 4 lalis@inf.uth.gr

Προσέγγιση Α Έχουμε συνειδητοποιήσει το πρόβλημα Γράφουμε κώδικα που επιτυγχάνει το επιθυμητό αποτέλεσμα ανεξάρτητα από την μη ατομικότητα των εντολών και τις εναλλαγές που ίσως γίνουν κατά την διάρκεια της εκτέλεσης του κώδικα Όμως Ο προγραμματιστής πρέπει να σκέφτεται / λύνει παρόμοια προβλήματα, κάθε φορά από την αρχή Υπάρχουν προβλήματα συγχρονισμού ανάμεσα σε νήματα που δεν μπορούν να λυθούν με απλό τρόπο 5 lalis@inf.uth.gr

Προσέγγιση Β Προσπαθούμε να μοντελοποιήσουμε το πρόβλημα και την λύση του με γενικό τρόπο, έτσι ώστε να μπορεί να χρησιμοποιηθεί σε πολλές περιπτώσεις Θετικά Η λύση είναι επαναχρησιμοποιήσιμη Διευκολύνεται η κατασκευή ορθών προγραμμάτων Αρνητικά Η γενική λύση ίσως επιφέρει επιπλέον κόστος εκτέλεσης (overhead) 6 lalis@inf.uth.gr

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

P Q R p1; p2; p3; p4; p5; p6; p7; p8; p9; q1; q2; q3; q4; q5; q6; q7; q8; q9; r1; r2; r3; r4; r5; r6; r7; r8; r9; 8 lalis@inf.uth.gr

P Q R p1; p2; p3; p4; p5; p6; p7; p8; p9; q1; q2; q3; q4; q5; q6; q7; q8; q9; r1; r2; r3; r4; r5; r6; r7; r8; r9; 9 lalis@inf.uth.gr

P Q R p1; p2; p3; p4; p5; p6; p7; p8; p9; q1; q2; q3; q4; q5; q6; q7; q8; q9; r1; r2; r3; r4; r5; r6; r7; r8; r9; 10 lalis@inf.uth.gr

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

int i=0; P1: int k; for (k=0; k<n; k++) { i=i+1; } P2: int k; for (k=0; k<n; k++) { i=i+1; } Επιθυμητή λειτουργικότητα: στο τέλος της εκτέλεσης η i πρέπει να έχει την τιμή 2Ν οι εντολές i=i+1 αποτελούν κρίσιμο τμήμα 12 lalis@inf.uth.gr

int i=0; P1: while (i<2*n) { i=i+1; } P2: while (i<2*n) { i=i+1; } Επιθυμητή λειτουργικότητα: στο τέλος της εκτέλεσης η i πρέπει να έχει την τιμή >=2Ν οι εντολές i=i+1 δεν αποτελούν κρίσιμο τμήμα 13 lalis@inf.uth.gr

Ιδιότητες της λύσης του ΚΤ 1. Αμοιβαίος αποκλεισμός (mutual exclusion): αν ένα νήμα βρίσκεται μέσα στο ΚΤ του, τότε κανένα άλλο νήμα δεν θα εισέλθει στο δικό του ΚΤ 2. Πρόοδος (progress): αν ένα νήμα επιθυμεί να εισέλθει στο ΚΤ του, τελικά θα το καταφέρει Απουσία αδιεξόδου (no deadlock): δεν υπάρχει περίπτωση τα νήματα να εμποδίζουν το ένα το άλλο από το να εισέλθει στο ΚΤ έτσι ώστε κανένα νήμα να μην καταφέρει ποτέ να εισέλθει στο ΚΤ Απουσία λιμοκτονίας (no starvation): δεν υπάρχει περίπτωση ένα συγκεκριμένο νήμα να μην καταφέρει ποτέ να μπει στο ΚΤ ενώ άλλα νήματα το καταφέρνουν ή δεν ενδιαφέρονται ούτε καν να μπουν στο ΚΤ 14 lalis@inf.uth.gr

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

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

P0 P1 EntryCode0 EntryCode1 ΚΤ του P0 CS μας ενδιαφέρει αυτός ο κώδικας CS ΚΤ του P1 ExitCode0 ExitCode1 17 lalis@inf.uth.gr

P1 P2 P3 P1 P2 P3 1) 2) CS CS P1 P2 P3 P2 P3 3) CS 4) P1 CS P1 18 lalis@inf.uth.gr

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

Υποθέσεις εργασίας Ένα νήμα που είναι έτοιμο προς εκτέλεση (ready state) κάποια στιγμή θα λάβει τον επεξεργαστή δεν υπάρχει λιμοκτονία σε επίπεδο χρονοπρογραμματισμού Δεν γίνεται καμία υπόθεση για το αν/πότε γίνεται εναλλαγή ανάμεσα στα νήματα, και την σειρά με την οποία θα τους δοθεί ο επεξεργαστής Δεν γίνεται καμία υπόθεση για το αν και πόσες φορές ένα νήμα θα θελήσει να εισέλθει στο ΚΤ Ένα νήμα δεν τερματίζεται κατά την εκτέλεση του κώδικα εισόδου/εξόδου ούτε μέσα στο ΚΤ Ένα νήμα δεν μένει για πάντα μέσα στο ΚΤ Για αρχή, υποθέτουμε μόνο 2 νήματα 20 lalis@inf.uth.gr

Αλγόριθμος Α1 int turn=p; P p1: p2: while (turn!=p) nop; p3: CS p4: turn=q; p5: Q q1: q2: while (turn!=q) nop; q3: CS q4: turn=p; q5: Ένα νήμα εισέρχεται στο ΚΤ όταν είναι η σειρά του Όταν βγει από το ΚΤ, δίνει ρητά σειρά στο άλλο νήμα 21 lalis@inf.uth.gr

Αλγόριθμος Α1 int turn=p; P p1: p2: while (turn!=p) nop; p3: CS p4: turn=q; p5: Q q1: q2: while (turn!=q) nop; q3: CS q4: turn=p; q5: Ένα νήμα εισέρχεται στο ΚΤ όταν είναι η σειρά του Όταν βγει από το ΚΤ, δίνει ρητά σειρά στο άλλο νήμα Εγγυάται αμοιβαίο αποκλεισμό Εγγυάται απουσία αδιεξόδου Δεν εγγυάται απουσία λιμοκτονίας 22 lalis@inf.uth.gr

turn=p p1: p2: while (turn!=p) nop /* turn is P */ p3: CS q1: q1: p3: CS p4: turn=q p5: q1: q1: p2: while (turn!=p) nop /* turn is Q */ p2: while (turn!=p) nop /* turn is Q */ p2: while (turn!=p) nop /* turn is Q */ q1: q1: 23 lalis@inf.uth.gr

Αλγόριθμος A2 int turn; P p1: p2: turn=p; p3: while (turn!=p) nop; p4: CS p5: turn=q; p6: Q q1: q2: turn=q; q3: while (turn!=q) nop; q4: CS q5: turn=p; q6: Όπως προηγουμένως, αλλά τώρα κάθε νήμα δίνει προκαταβολικά σειρά στον εαυτό του 24 lalis@inf.uth.gr

Αλγόριθμος A2 int turn; P p1: p2: turn=p; p3: while (turn!=p) nop; p4: CS p5: turn=q; p6: Q q1: q2: turn=q; q3: while (turn!=q) nop; q4: CS q5: turn=p; q6: Όπως προηγουμένως, αλλά τώρα κάθε νήμα δίνει προκαταβολικά σειρά στον εαυτό του Δεν εγγυάται αμοιβαίο αποκλεισμό 25 lalis@inf.uth.gr

p1: p2: turn=p p3: while (turn!=p) nop /* turn is P */ p4: CS p4: CS p4: CS q1: q1: q2: turn=q q3: while (turn!=q) nop /* turn is Q */ q4: CS q4: CS 26 lalis@inf.uth.gr

Αλγόριθμος Β1 boolean wantp=false,wantq=false; P p1: p2: while (wantq) nop; p3: wantp=true; p4: CS p5: wantp=false; p6: Q q1: q2: while (wantp) nop; q3: wantq=true; q4: CS q5: wantq=false; q6: Χρησιμοποιούμε ξεχωριστές μεταβλητές για την πρόθεση εισόδου κάθε νήματος στο ΚΤ Προτού ένα νήμα εισέλθει στο ΚΤ, ελέγχει την πρόθεση του άλλου, και αν ισχύει τότε περιμένει 27 lalis@inf.uth.gr

Αλγόριθμος Β1 boolean wantp=false,wantq=false; P p1: p2: while (wantq) nop; p3: wantp=true; p4: CS p5: wantp=false; p6: Q q1: q2: while (wantp) nop; q3: wantq=true; q4: CS q5: wantq=false; q6: Χρησιμοποιούμε ξεχωριστές μεταβλητές για την πρόθεση εισόδου κάθε νήματος στο ΚΤ Προτού ένα νήμα εισέλθει στο ΚΤ, ελέγχει την πρόθεση του άλλου, και αν ισχύει τότε περιμένει Δεν εγγυάται αμοιβαίο αποκλεισμό 28 lalis@inf.uth.gr

wantp=false, wantq=false p1: p1: p2: while (wantq) nop /* wantq is false */ q1: q1: q2: while (wantp) nop /* wantp is false */ q3: wantq=true q4: CS q4: CS q4: CS p3: wantp=true p4: CS p4: CS p4: CS 29 lalis@inf.uth.gr

Αλγόριθμος B2 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) nop; p4: CS p5: wantp=false; p6: Q q1: q2: wantq=true; q3: while (wantp) nop; q4: CS q5: wantq=false; q6: Όπως προηγουμένως, αλλά τώρα κάθε νήμα δηλώνει τον πρόθεση του να εισέλθει στο ΚΤ προτού ελέγξει την πρόθεση του άλλου νήματος 30 lalis@inf.uth.gr

Αλγόριθμος B2 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) nop; p4: CS p5: wantp=false; p6: Q q1: q2: wantq=true; q3: while (wantp) nop; q4: CS q5: wantq=false; q6: Όπως προηγουμένως, αλλά τώρα κάθε νήμα δηλώνει τον πρόθεση του να εισέλθει στο ΚΤ προτού ελέγξει την πρόθεση του άλλου νήματος Εγγυάται αμοιβαίο αποκλεισμό Δεν εγγυάται απουσία αδιεξόδου 31 lalis@inf.uth.gr

wantp=false, wantq=false p1: p1: p2: wantp=true q1: q1: q2: wantq=true q3: while (wantp) nop /* wantp is true */ q3: while (wantp) nop /* wantp is true */ q3: while (wantp) nop /* wantp is true */ p3: while (wantq) nop /* wantq is true */ p3: while (wantq) nop /* wantq is true */ p3: while (wantq) nop /* wantq is true */ q3: while (wantp) nop /* wantp is true */ q3: while (wantp) nop /* wantp is true */ q3: while (wantp) nop /* wantp is true */ p3: while (wantq) nop /* wantq is true */ p3: while (wantq) nop /* wantq is true */ p3: while (wantq) nop /* wantq is true */ 32 lalis@inf.uth.gr

Αλγόριθμος B3 boolean wantp=false,wantq=false; P Q p1: p2: wantp=true; p3: while (wantq) { p4: wantp=false; p5: wantp=true; } p6: CS p7: wantp=false; p8: q1: q2: wantq=true; q3: while (wantp) { q4: wantq=false; q5: wantq=true; } q6: CS q7: wantq=false; q8: Όπως προηγουμένως, αλλά κατά την αναμονή γίνεται προσωρινή «παραίτηση» από την πρόθεση εισόδου 33 lalis@inf.uth.gr

Αλγόριθμος B3 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) { p4: wantp=false; p5: wantp=true; } p6: CS p7: wantp=false; p8: Q q1: q2: wantq=true; q3: while (wantp) { q4: wantq=false; q5: wantq=true; } q6: CS q7: wantq=false; q8: Όπως προηγουμένως, αλλά κατά την αναμονή γίνεται προσωρινή «παραίτηση» από την πρόθεση εισόδου Εγγυάται αμοιβαίο αποκλεισμό γιατί; Δεν εγγυάται πρόοδο γιατί; 34 lalis@inf.uth.gr

wantp=false, wantq=false p1: p2: wantp=true q1: q2: wantq=true q3: while (wantp) /* wantp is true */ q4: wantq=false q5: wantq=true p3: while (wantq) {} /* wantq is true */ p4: wantp=false p5: wantp=true p3: while (wantq) {} /* wantq is true */ q3: while (wantp) {} /* wantp is true */ q4: wantq=false q5: wantq=true p4: wantp=false p5: wantp=true p3: while (wantq) {} /* wantq is true */ 35 lalis@inf.uth.gr

Παρατηρήσεις H λύση είναι τυπικά λανθασμένη Παρόλα αυτά, μια τέτοια «ατυχής» εναλλαγή θα μπορούσε να θεωρηθεί εντελώς απίθανη στην πράξη η λύση θα μπορούσε να χαρακτηριστεί ως ικανοποιητική (τουλάχιστον για μη-κρίσιμα συστήματα) Όμως, αυτή η υπόθεση απαιτεί προσοχή Π.χ. αν γίνεται συστηματική εναλλαγή κάθε εντολή υπάρχει σίγουρο αδιέξοδο Μπορεί να μειωθεί η πιθανότητα μιας «ατυχούς» εκτέλεσης, έτσι ώστε η λύση να δουλεύει σωστά με μεγάλη πιθανότητα; 36 lalis@inf.uth.gr

Αλγόριθμος B4 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) { p4: wantp=false; p5: sleep(random); p6: wantp=true; } p7: CS p8: wantp=false; p9: Q q1: q2: wantq=true; q3: while (wantp) { q4: wantq=false; q5: sleep(random); q6: wantq=true; } q7: CS q8: wantq=false; q9: Υπάρχει εγγύηση προόδου; 37 lalis@inf.uth.gr

Αλγόριθμος B5 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) { p4: wantp=false; p5: while (wantq) nop; p6: wantp=true; } p7: CS p8: wantp=false; p9: Q q1: q2: wantq=true; q3: while (wantp) { q4: wantq=false; q5: nop; q6: wantq=true; } q7: CS q8: wantq=false; q9: Υπάρχει εγγύηση προόδου; 38 lalis@inf.uth.gr

Αλγόριθμος B6 boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) { p4: wantp=false; p5: while (wantq) nop; p6: wantp=true; } p7: CS p8: wantp=false; p9: Q q1: q2: wantq=true; q3: while (wantp) { } q4: CS q5: wantq=false; q6: Υπάρχει εγγύηση προόδου; 39 lalis@inf.uth.gr

Παρατήρηση Πως μπορούμε να εγγυηθούμε ότι το νήμα που παραχωρεί την θέση του δεν θα προσπερνιέται επ άπειρο από το άλλο νήμα, σε περίπτωση συνεχούς ανταγωνισμού; Επαναφέρουμε την ιδέα του αλγορίθμου Α1, δηλαδή την αυστηρά εναλλάξ σειρά εισόδου στο ΚΤ Αυτή το φορά, μόνο αν υπάρχει ανταγωνισμός το γνωρίζουμε λόγω των μεταβλητών wantp/wantq 40 lalis@inf.uth.gr

Αλγόριθμος Dekker int turn=p; boolean wantp=false,wantq=false; P p1: p2: wantp=true; p3: while (wantq) { p4: if (turn!=p) { p5: wantp=false; p6: while (turn!=p) nop; p7: wantp=true; } } p8: CS p9: turn=q; p10: wantp=false; p11: Q q1: q2: wantq=true; q3: while (wantp) { q4: if (turn!=q) { q5: wantq=false; q6: while (turn!=q) nop; q7: wantq=true; } } q8: CS q9: turn=p; q10: wantq=false; q11: 41 lalis@inf.uth.gr

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

Ένας ακόμα αλγόριθμος Συνδυασμός ελέγχου των δύο συνθηκών εισόδου που υπάρχουν ήδη στον αλγόριθμο του Dekker 1) Μήπως επιχειρεί και το άλλο νήμα να μπει στο ΚΤ αυτή τη στιγμή; 2) Μήπως είναι η σειρά μου να μπω στο ΚΤ; Μόνο ένας βρόγχος αναμονής, μέσω του οποίου πραγματοποιούνται και οι δύο παραπάνω έλεγχοι 48 lalis@inf.uth.gr

Μια πρώτη απόπειρα int turn=p; int wantp=false,wantq=false; P wantp=true; while (wantq) { if (turn==p) { break; } } Q wantq=true; while (wantp) { if (turn==q) { break; } } CS CS turn=q; wantp=false; turn=p; wantq=false; 49 lalis@inf.uth.gr

Μια πρώτη απόπειρα int turn=p; int wantp=false,wantq=false; P wantp=true; while (wantq) { if (turn==p) { break; } } Q wantq=true; while (wantp) { if (turn==q) { break; } } CS CS turn=q; wantp=false; turn=p; wantq=false; Γιατί αυτή η λύση δεν είναι σωστή; 50 lalis@inf.uth.gr

Αλγόριθμος Peterson int turn; int wantp=false,wantq=false; P wantp=true; turn=q; while (wantq) { if (turn==p) { break; } } Q wantq=true; turn=p; while (wantp) { if (turn==q) { break; } } CS CS wantp=false; wantq=false; 51 lalis@inf.uth.gr

Αλγόριθμος Peterson int turn; int wantp=false,wantq=false; P wantp=true; turn=q; while ((wantq) && (turn!=p)) {} Q wantq=true; turn=p; while ((wantp) && (turn!=q)) {} CS CS wantp=false; wantq=false; 52 lalis@inf.uth.gr

Παρατήρηση Όπως και στον A2, και τα δύο νήματα αλλάζουν και ελέγχουν την turn ταυτόχρονα μεταξύ τους Αντίθετα με τον A2, σε αυτή την περίπτωση είναι εγγυημένος ο αμοιβαίος αποκλεισμός γιατί όταν ένα νήμα αλλάζει την turn τότε δίνει προτεραιότητα στο άλλο (και όχι στον εαυτό του) Ο αλγόριθμος δεν θα ήταν σωστός αν κάθε νήμα που επιχειρεί να εισέλθει στο ΚΤ έδινε προτεραιότητα στον εαυτό του (Α2) η αλλαγή της turn (υπέρ του άλλου νήματος) γινόταν μετά την έξοδο από το ΚΤ (Α1) 53 lalis@inf.uth.gr

Αλγόριθμος Bakery (Lamport) Σε περίπτωση ανταγωνισμού, η προτεραιότητα καθορίζεται μέσω ενός εισιτηρίου (ticket) t[i] Αν το Pi δεν έχει πρόθεση να μπει στο ΚΤ, t[i]==0 Διαφορετικά, το Pi λαμβάνει το εισιτήριο του t[i] αυξάνοντας κατά 1 το εισιτήριο t[(i+1)%2] του ανταγωνιστικού νήματος P(i+1)%2 Το νήμα με τον μικρότερο αριθμό εισέρχεται στο ΚΤ Δεν υπάρχει περίπτωση ένα νήμα να εισέλθει δύο συνεχόμενες φορές στο ΚΤ ενώ περιμένει το άλλο Στην δεύτερη απόπειρα θα λάβει σίγουρα μεγαλύτερο αριθμό εισιτηρίου από το νήμα που ήδη περιμένει να μπει στο ΚΤ 54 lalis@inf.uth.gr

Σύγκριση εισιτηρίων / προτεραιότητας bool priority(i) { if (t[i]==0) // Pi not competing => I have priority return(false); else if (t[self]<t[i]) // I have priority return(false); else if (t[self]>t[i]) // Pi has priority return(true); else // same ticket nr => tie-break based on ids return(self>i); } Λόγω ταυτόχρονης εκτέλεσης, διαφορετικά νήματα μπορεί να έχουν τον ίδιο αριθμό εισιτηρίου > 0 Για να σπάσει το αδιέξοδο, προτεραιότητα εισόδου στο ΚΤ δίνεται στο νήμα με το μικρότερο αναγνωριστικό 55 lalis@inf.uth.gr

Αλγόριθμος Bakery / FIFO (Lamport) int t[2]={0,0}; bool taking[2]={false,false}; P0: taking[0]=true; t[0] = t[1] + 1; taking[0]=false; while (taking[1]) {} while (priority(1)) {} CS0 t[0]=0; P1 taking[1]=true; t[1] = t[0] + 1; taking[1]=false; while (taking[0]) {} while (priority(0)) {} CS1 t[1]=0; 56 lalis@inf.uth.gr

Η μεταβλητή taking Αν taking[i]==true, το εισιτήριο του Pi βρίσκεται υπό κατασκευή, και δεν μπορεί να χρησιμοποιηθεί για τον έλεγχο προτεραιότητας Αν taking[i]==false, το εισιτήριο του Pi μπορεί να χρησιμοποιηθεί με ασφάλεια για τον έλεγχο προτεραιότητας Αν, αφού ένα νήμα ελέγξει ότι taking[i]==false, αλλά προτού ελέγξει την προτεραιότητα, το Pi βγάλει εισιτήριο, αυτό θα είναι εγγυημένα μεγαλύτερο από το εισιτήριο του άλλου νήματος Προσοχή: αυτό δεν εμποδίζει τα δύο νήματα να κατασκευάσουν τα εισιτήρια τους ταυτόχρονα 57 lalis@inf.uth.gr

Αλγόριθμος Bakery / FIFO (Lamport) int t[2]={0,0}; int taking[2]={false,false}; P0: taking[0]=true; tmp0 = t[1]; t[0] = tmp0 + 1; taking[0]=false; while (taking[1]) {} while (priority(1)) {} CS0 t[0]=0; P1: taking[1]=true; tmp1 = t[0]; t[1] = tmp1 + 1; taking[1]=false; while (taking[0]) {} while (priority(0)){} CS1 t[1]=0; 58 lalis@inf.uth.gr

Χωρίς την «προστασία» της taking t[0]=0, t[1]=0 P0: tmp0=t[1] /* tmp0 is 0 */ P1: tmp1=t[0] /* tmp1 is 0 */ P1: t[1]=tmp1+1 /* t[1] is 1 */ P1: while (priority(0)) /* false */ P1: CS P0: t[0]=tmp0+1 /* t[0] is 1 */ P0: while(priority(1)) /* false */ P0: CS 59 lalis@inf.uth.gr

Αλγόριθμος Bakery για Ν νήματα int t[ν]={0,,0}; int taking[ν]={false,,false}; Pi taking[i]=true; t[i] = max(t[0],t[1],, t[n-1]) + 1; taking[i]=false; for (j=0; j<ν; j++) { while (taking[j]) {} while (priority(j)) {} } CS t[i]=0; 60 lalis@inf.uth.gr

Παρατηρήσεις Οι προηγούμενες λύσεις βασίζονται αποκλειστικά σε συμβατικό κώδικα (είναι γενικότερα εφαρμόσιμες) Χωρίς να γίνεται καμία (περιοριστική) υπόθεση εργασίας για την εκτέλεση των νημάτων Χωρίς να υπάρχει κανένας έλεγχος της εναλλαγής Χωρίς να γίνεται χρήση ειδικών εντολών υλικού Όμως: Για κάθε ΚΤ χρειάζεται ξεχωριστό σετ μεταβλητών Υπάρχει ενεργή αναμονή Ο αριθμός των ανταγωνιστικών νημάτων ανά ΚΤ πρέπει να είναι γνωστός εκ των προτέρων 61 lalis@inf.uth.gr

Ειδικές εντολές σε επίπεδο υλικού Οι επεξεργαστές προσφέρουν ειδικές ατομικές εντολές που μπορεί να χρησιμοποιηθούν για τον συγχρονισμό ανάμεσα σε νήματα με κοινή μνήμη Π.χ. test-and-set ή compare-and-swap int TAS(int *v) { int oldv; int CAS(int* v, int curv, int newv) { int oldv; } ATOMIC oldv=*v; *v=1; END_ATOMIC return(oldv); } ATOMIC oldv = *v; if (oldv == curv) *v=newv; END_ATOMIC return(oldv); 62 lalis@inf.uth.gr

Κρίσιμο τμήμα με TAS και CAS int lock=0; Pi: while (TAS(&lock)){} CS lock = 0; int lock=0; Pi: while (CAS(&lock,0,1)){} CS lock = 0; 63 lalis@inf.uth.gr

Κρίσιμο τμήμα με TAS και CAS int lock=0; Pi: while (TAS(&lock)){} CS lock = 0; int lock=0; Pi: while (CAS(&lock,0,1)){} CS lock = 0; Η λύση ισχύει για άγνωστο αριθμό νημάτων Δεν εγγυάται πρόοδο γιατί; 64 lalis@inf.uth.gr

Χωρίς ενεργή αναμονή 65 lalis@inf.uth.gr

Ενεργή αναμονή (busy waiting) Κατά την αναμονή στον κώδικα εισόδου τα νήματα ξοδεύουν χρόνο του επεξεργαστή χωρίς νόημα «σπινάρουν» γύρω από την μια συνθήκη αναμονής που δεν μπορεί να αλλάξει όσο κρατάνε τον επεξεργαστή Αυτό καθυστερεί την πρόοδο των υπολοίπων νημάτων συμπεριλαμβανομένου και του νήματος που βρίσκεται μέσα στο ΚΤ Όσο περισσότερα νήματα εκτελούν ενεργή αναμονή, τόσο πιο αργά προοδεύει το νήμα που βρίσκεται μέσα στο ΚΤ και τόσο πιο αργά θα ελευθερωθεί το ΚΤ για να μπορέσει να εισέλθει το επόμενο νήμα 66 lalis@inf.uth.gr

P0 P1 P0: CS0 P0: CS0 P0: CS0 P1: while () P1: while () P1: while () P0: CS0 P0: CS0 P0: CS0 P1: while () P1: while () P1: while () P0: CS0 P0: CS0 P0: CS0 P1: while () 67 lalis@inf.uth.gr

Εθελοντική (ρητή) εναλλαγή Όσο ισχύει η συνθήκη αναμονής, το νήμα μπορεί να παραχωρήσει (εθελοντικά) την CPU ώστε να συνεχιστεί η εκτέλεση ενός άλλου νήματος που μπορεί να προοδεύσει, όπως το νήμα που βρίσκεται στο ΚΤ Ο χαμένος χρόνος της CPU μειώνεται σημαντικά χωρίς ρητή εναλλαγή while (<cond>) {} CS falsify <cond> με ρητή εναλλαγή while (<cond>) {yield();} CS falsify <cond> yield(); /* be nice */ 68 lalis@inf.uth.gr

P0 P1 P0: CS0 P0: CS0 P0: CS0 P1: while () yield() P0: CS0 P0: CS0 P0: CS0 P1: while () yield() P0: CS0 P0: CS0 P0: CS0 P1: while () yield() P0: CS0 P0: CS0 P0: CS0 P1: while () yield() P0: CS0 69 lalis@inf.uth.gr

Χωρίς ενεργή αναμονή Η ρητή παραχώρηση του επεξεργαστή δεν λύνει εντελώς το πρόβλημα της ενεργής αναμονής Απλά το κάνει λιγότερο επώδυνο Εξακολουθεί να χάνεται χρόνος του επεξεργαστή για τον έλεγχο της συνθήκης αναμονής και την εναλλαγή Το ιδανικό Τα νήματα να απενεργοποιούνται πλήρως, μέχρι να έρθει η σειρά τους να εισέλθουν στο ΚΤ 70 lalis@inf.uth.gr

Απαλοιφή ενεργής αναμονής Έστω ότι το σύστημα εκτέλεσης παρέχει ειδικές λειτουργίες αναμονής/αφύπνισης WAIT / WAKEUP Η απαλοιφή της ενεργής αναμονής φαίνεται μάλλον εύκολη υπόθεση Αντί το νήμα να ελέγχει συνεχώς/ενεργά την συνθήκη, καλεί την WAIT και μπαίνει σε αναμονή Αντίστοιχα, όταν ένα νήμα αλλάζει την συνθήκη, αφυπνίζει με την WAKEUP το νήμα που περιμένει Όμως, λύσεις τέτοιου τύπου είναι ιδιαίτερα ευάλωτες σε συνθήκες ανταγωνισμού 71 lalis@inf.uth.gr

int locked=0; Queue q; INIT(q); Pi: if (TAS(&locked)) { WAIT(q); } CS Γιατί αυτή η λύση δεν είναι σωστή; locked=0; WAKEUP(q); 72 lalis@inf.uth.gr

int locked=0; Queue q; INIT(q); Pi: while (TAS(&locked)) { WAIT(q); } CS Γιατί αυτή η λύση δεν είναι σωστή; locked=0; WAKEUP(q); 73 lalis@inf.uth.gr

Υποστήριξη συγχρονισμού σε ψηλό επίπεδο Ο έλεγχος της εναλλαγής και η εγγύηση ατομικής εκτέλεσης κώδικα υπάρχει συνήθως ως δυνατότητα μόνο στο επίπεδο/περιβάλλον που υλοποιεί τους μηχανισμούς της ταυτόχρονης εκτέλεσης, π.χ., λειτουργικό, βιβλιοθήκη νημάτων, Με την σειρά τους, τα περιβάλλοντα εκτέλεσης παρέχουν στον προγραμματιστή άλλα «εργαλεία» συγχρονισμού (σηματοφόροι, ελεγκτές, κλπ) που μπορεί να χρησιμοποιηθούν για να λυθούν τα προβλήματα συγχρονισμού, όπως το ΚΤ, χωρίς ενεργή αναμονή 74 lalis@inf.uth.gr

Η ενεργή αναμονή μπορεί να είναι καλή ιδέα Σε συστήματα με πολλές CPU, η ενεργή αναμονή (μέσω spinlocks) είναι λιγότερο προβληματική Απλά χάνεται ο χρόνος της CPU που τρέχει το νήμα που πραγματοποιεί ενεργή αναμονή (χωρίς να υπάρχει το κόστος μιας εναλλαγής) όμως δημιουργείται κίνηση προς την κοινή μνήμη Αν η πιθανότητα ανταγωνισμού είναι μικρή και η παραμονή των νημάτων στο ΚΤ είναι σύντομη, η ενεργή αναμονή μπορεί να είναι πιο αποδοτική από αναστολή/επαναφορά νημάτων μέσω κλήσεων συστήματος 75 lalis@inf.uth.gr

P1 P2 L1 TAS lock,tmp cmp tmp,0 brneq L1 // CS store 0,lock CPU lock shared memory L1 TAS lock,tmp cmp tmp,0 brneq L1 // CS store 0,lock CPU P1 P2 lock unlock lock unlock lock unlock CS CS spin CS lock unlock lock unlock lock unlock spin CS CS CS Προγραμματισμός ΙΙΙ 76 lalis@inf.uth.gr