ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ ΔΙΑΔΙΕΡΓΑΣΙΑΚΗ ΕΠΙΚΟΙΝΩΝΙΑ ΣΥΓΧΡΟΝΙΣΜΟΣ

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

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Νήµατα Εκτέλεσης Συγχρονισµός ιεργασιών σε Κοινή Μνήµη

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

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

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

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

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

Σκοπός Μαθήματος. Λειτουργικά Συστήματα Η/Υ. Γενικές Πληροφορίες. Στόχοι Μαθήματος ΚΕΦΑΛΑΙΟ 1 - ΕΙΣΑΓΩΓΗ. Θεωρία: Εργαστήριο: Κεφάλαιο 1 «Εισαγωγή»

Επιτεύγµατα των Λ.Σ.

1. Εισαγωγή. Λειτουργικά Συστήματα Η/Υ. Διεργασίες. Ορισμός ΚΕΦΑΛΑΙΟ 3 - ΔΙΕΡΓΑΣΙΕΣ. Κεφάλαιο 3 «Διεργασίες»

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

ΣυγχρονισµόςσεΣυστήµατα ΠολλαπλώνΝηµάτων

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

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

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

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

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

Εργαστήριο Λειτουργικών Συστημάτων 8o εξάμηνο, Ροή Υ, ΗΜΜΥ

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

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


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

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

Μάθημα 7 ο. Αλγόριθμοι Χρονοδρομολόγησης

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

Ενότητα 4 (Κεφάλαιο 5) Συντρέχων Προγραμματισμός

2.3 Επικοινωνία Διεργασιών

Συγχρονισμός. Συστήματα Παράλληλης Επεξεργασίας 9ο εξάμηνο ΣΗΜΜΥ ακ. έτος CSLab. Κορνήλιος Κούρτης

Ε-85: Ειδικά Θέµατα Λογισµικού

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

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

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

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

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

Παρουσίαση 5 ης Άσκησης:

Εισαγωγή στα Λειτουργικά συστήματα Ι. Καθηγητής Κώστας Αναγνωστόπουλος

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

Αδιέξοδα (Deadlocks)

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

ΚΕΦΑΛΑΙΟ 3: Λειτουργικά Συστήµατα

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

2. Σκοποί και Λειτουργίες των ΛΣ. Λειτουργικά Συστήματα Η/Υ. Περίληψη. Ι. Προστασία Υλικού ΚΕΦΑΛΑΙΟ 2 - ΕΞΕΛΙΞΗ ΚΑΙ ΣΚΟΠΟΙ ΛΣ

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

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

Προγραμματισμός με Κοινόχρηστο Χώρο Διευθύνσεων 4

Η πολυνηματική γλώσσα προγραμματισμού Cilk

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

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

HY-486 Αρχές Κατανεμημένου Υπολογισμού Εαρινό Εξάμηνο

Παρουσίαση 5 ης Άσκησης:

Εισαγωγή στην Πληροφορική

HY-486 Αρχές Κατανεμημένου Υπολογισμού

Ενότητα 2 (Κεφάλαιο 3) Περιγραφή και Έλεγχος Διεργασιών. Περιεχόμενα. Ανάγκη ύπαρξης διεργασιών 1

Ανάλυση Επιδόσεων Συστημάτων Πραγματικού Χρόνου

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

ΛΟΓΙΣΜΙΚΟ (software)

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

Περιγραφή και Έλεγχος ιεργασιών

3.1 Λειτουργικό Σύστηµα. Λειτουργικό Σύστηµα (2) ΚΕΦΑΛΑΙΟ 3: Λειτουργικά Συστήµατα. Ο υπολογιστής σαν σκέτο hardware έχει περιορισµένη χρησιµότητα

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

1. ΑΡΧΕΣ ΛΕΙΤΟΥΡΓΙΚΩΝ ΣΥΣΤΗΜΑΤΩΝ

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

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ. Χρονοπρογραμματισμός Εργαστηριακές Ασκήσεις

Εικονική Μνήμη (Virtual Μemory)

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

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

Transcript:

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Διάλεξη 4 ΔΙΑΔΙΕΡΓΑΣΙΑΚΗ ΕΠΙΚΟΙΝΩΝΙΑ ΣΥΓΧΡΟΝΙΣΜΟΣ Οι διαφάνειες έχουν καθαρά επικουρικό χαρακτήρα στην παρουσίαση των διαλέξεων του μαθήματος. Δεν αντικαθιστούν σε καμία περίπτωση την παρακάτω βιβλιογραφία που αποτελεί και το βασικό εγχειρίδιο αναφοράς. Βιβλιογραφία: Σύγχρονα Λειτουργικά Συστήματα, A.S. Tanenbaum, 3 η έκδ., Κλειδάριθμος, 2009. Λειτουργικά Συστήματα, W. Stallings, 8 η έκδ., Τζιόλα, 2015. Λειτουργικά Συστήματα, A. Silberschatz, P. Galvin, G. Gagne, 7 η εκδ., ΙΩΝ, 2007.

Στόχοι Η διάλεξη αυτή έχει ως στόχο να εισάγει τον σπουδαστή στα προβλήματα συνεργασίας και επικοινωνίας μεταξύ των διεργασιών/νημάτων, και ειδικότερα: να γνωρίσει τα προβλήματα συγχρονισμού των διεργασιών/νημάτων και τις μεθόδους που χρησιμοποιούνται για την αντιμετώπισή τους να είναι σε θέση να εφαρμόσει τις παραπάνω μεθόδους για να επιλύσει προβλήματα να γνωρίσει κλασικά προβλήματα συγχρονισμού και τις προτεινόμενες λύσεις 2

Ενότητες Συγχρονισμός και συνεργασία διεργασιών Προβλήματα συγχρονισμού Λύσεις συγχρονισμού Απαιτήσεις της λύσης του κρίσιμου τμήματος Αμοιβαίος αποκλεισμός και υλοποιήσεις Σημαφόροι Δυαδικοί σημαφόροι ή mutexes Κλασικά προβλήματα συγχρονισμού Ελεγκτές ή παρακολουθητές και μεταβλητές συνθήκης Διαδιεργασιακή επικοινωνία Ερωτήσεις 3

Συγχρονισμός και συνεργασία διεργασιών (Process synchronization) Σε ένα ΛΣ ενός ή περισσοτέρων επεξεργαστών πολλαπλές διεργασίες ή νήματα που εκτελούνται ταυτόχρονα ή παράλληλα, μπορούν να έχουν πρόσβαση (ανάγνωση/εγγραφή) σε κοινούς πόρους στη μνήμη, κοινά δεδομένα (data sharing) π.χ. καθολικές μεταβλητές, αρχεία, συσκευές Ε/Ε. Αυτός ο διαμοιρασμός της κύριας μνήμης και πόρων (resource sharing) μεταξύ διεργασιών είναι χρήσιμος για την εξασφάλιση της αποδοτικής αλληλεπίδρασης (συνεργασίας) μεταξύ των διεργασιών. Πηγή εικόνας: https://computing.llnl.gov/tutorials/parallel_comp/

Αυτή η δυνατότητα πρόσβασης σε κοινά δεδομένα είναι ακόμα πιο εύκολη για τα νήματα (threads) που εκτελούνται ταυτόχρονα ή παράλληλα μέσα σε μια διεργασία (process), καθώς αυτά μοιράζονται τον κοινό χώρο διευθύνσεων και πόρων αυτής. Νήματα βέβαια διαφορετικών χώρων διευθύνσεων (δηλ. διαφορετικών διεργασιών) ακολουθούν παρομοίως τους κανόνες πρόσβασης και διαμοιρασμού των πόρων που ισχύουν για τις διεργασίες. 5

Προβλήματα συγχρονισμού της πρόσβασης σε κοινά δεδομένα Όμως προκύπτουν προβλήματα διαχείρισης της πρόσβασης σε διαμοιραζόμενους πόρους, με συνέπεια την αναγκαιότητα ελέγχου και συγχρονισμού αυτής της πρόσβασης για την προστασία των διαμοιραζόμενων πόρων και για την αξιόπιστη επεξεργασία αυτών. Σύνηθες πρόβλημα είναι της ανακολουθίας ή ασυνέπειας των δεδομένων και φυσικά και των αποτελεσμάτων (data inconsistency). Το πρόβλημα αυτό της μη συνεπής χρήσης των δεδομένων μπορεί να προκύψει στις διεργασίες και νήματα που έχουν (ταυτόχρονη) πρόσβαση σε όλες τις καθολικές μεταβλητές (shared data) και τα κοινά δυναμικά δεδομένα ενός προγράμματος στη μνήμη. Στη συνέχεια εξετάζονται δύο χαρακτηριστικές καταστάσεις οι οποίες οδηγούν σε τέτοιου είδους προβλήματα. 6

Δύο χαρακτηριστικές καταστάσεις από τις οποίες προκύπτουν προβλήματα είναι οι ακόλουθες: (α) Η διακοπή της εκτέλεσης του κώδικα μιας διεργασίας (interrupt), χωρίς να έχει προλάβει να ολοκληρώσει την επεξεργασία της όσον αφορά τα κοινά δεδομένα. Όσο περιμένει κάποια άλλη ενδέχεται να τα τροποποιήσει. program2 (β) Δύο ή περισσότερες διεργασίες προσπαθούν να προσπελάσουν ταυτόχρονα (την ίδια χρονική στιγμή) κοινόχρηστα δεδομένα (shared data). 7

(α) Κατάσταση όπου η εκτέλεση του κώδικα μιας διεργασίας διακοπεί (interrupt), ίσως και περισσότερες φορές, σε οποιοδήποτε σημείο, από τις ρουτίνες χειρισμού διακοπών (interrupt handler), για την εξυπηρέτηση κάποιας άλλης κλήσης ή για άλλους λόγους, χωρίς να έχει προλάβει να ολοκληρώσει την επεξεργασία της όσον αφορά τα κοινά δεδομένα. Σε αυτή την περίπτωση το πρόβλημα το οποίο είναι πιθανό να συμβεί είναι κάποια άλλη διεργασία να προχωρήσει στην επεξεργασία αυτών των κοινών δεδομένων, με αποτέλεσμα να έχουμε αποτυχία στη διασφάλιση της ακεραιότητας των δεδομένων (ασυνέπεια δεδομένων, data inconsistency). Π.χ. μια διεργασία (P1) ενώ πραγματοποιούσε ενημέρωση κάποιας καθολικής μεταβλητής (v) διακόπηκε χωρίς να έχει ολοκληρώσει. Στη συνέχεια κάποια άλλη διεργασία (P2) την τροποποιεί, με συνέπεια όταν η αρχική επανέλθει να συνεχίσει, αυτό το δεδομένο να έχει διαφορετικό περιεχόμενο, και έτσι να αποτελέσει πρόβλημα στην ορθότητα της εκτέλεσής της και των αποτελεσμάτων της. data shared v 8

(β) Κατάσταση όπου δύο ή περισσότερες διεργασίες προσπαθούν να προσπελάσουν ταυτόχρονα (την ίδια χρονική στιγμή) κοινόχρηστα δεδομένα (shared data). Αναφέρεται και ως κατάσταση συναγωνισμού (race condition). Σε αυτή την περίπτωση το πρόβλημα το οποίο είναι πιθανό να συμβεί είναι και πάλι η ενδεχόμενη ανακολουθία στην επεξεργασία των δεδομένων (ασυνέπεια των δεδομένων/αποτελεσμάτων). Π.χ. μια διεργασία (B) διαβάζει μια καθολική μεταβλητή (v) ενώ κάποια άλλη διεργασία (A) τη γράφει, ή περισσότερες από μια διεργασίες την τροποποιούν την ίδια στιγμή. v v Η τελική τιμή των κοινών δεδομένων εξαρτάται από το πως θα δρομολογηθεί από το ΛΣ η επιμέρους εκτέλεση του κώδικα των διεργασιών (process scheduling). 9

Παράδειγμα: πρόσβαση σε κοινή μεταβλητή (shared variable) Έστω πως δύο νήματα εκτελούν τον παρακάτω κώδικα: int i=0; /* κοινή μεταβλητή */ void body { i++; } Ερώτημα: ποια η τιμή της μεταβλητής i αφού εκτελεσθούν τα δυο νήματα; Απάντηση: μπορεί να είναι 1 ή 2, δεν το γνωρίζουμε, καθώς η κάθε εκτέλεση μπορεί να δίνει διαφορετικό αποτέλεσμα. Αυτό συμβαίνει διότι η εκτέλεση της εντολής i++ δεν είναι (εγγυημένα) ατομική (atomic), δηλαδή χωρίς να υπάρχει πιθανότητα διακοπής της, και έτσι να μεσολαβεί και να συνεχίζει η άλλη διεργασία και να μεταβάλλει το περιεχόμενό της. 10

Η εντολή i++ μεταφράζεται σε γλώσσα μηχανής. Συμβολικά (pseudo-assembly) θα μπορούσε να έχει ως εξής: regx = mem[i_adr]; - φόρτωση του περιεχομένου μνήμης της i regx = regx+1; - αύξηση του περιεχομένου της +1 mem[i_adr] = regx; - τοποθέτηση του αποτελέσματος στην i Σενάρια εκτέλεσης Αρχικά η μεταβλητή i έχει την τιμή 0. Η εκτέλεση εξαρτάται από την (τυχαία) χρονοδρομολόγηση του ΛΣ. Η σειριακή εκτέλεση του κώδικα των διεργασιών ενδέχεται να δίνει διαφορετικό αποτέλεσμα από μια διαπλεκόμενη εκτέλεσή του. Σενάριο Α (serial) thread 1: reg1 = mem[i_adr]; thread 1: reg1 = reg+1; thread 1: mem[i_adr] = reg1; thread 2: reg2 = mem[i_adr]; thread 2: reg2 = reg2+1; thread 2: mem[i_adr] = reg2; Η μεταβλητή i παίρνει την τιμή 2 Σενάριο Β (interleaved) thread 1: reg1 = mem[i_adr]; thread 1: reg1 = reg+1; thread 2: reg2 = mem[i_adr]; thread 2: reg2 = reg2+1; thread 2: mem[i_adr] = reg2; thread 1: mem[i_adr] = reg1; Η μεταβλητή i παίρνει την τιμή 1 The results of computations depends on the order in which these operations are performed.

Λύσεις συγχρονισμού της πρόσβασης σε κοινά δεδομένα Μηχανισμοί (μέθοδοι) που διαχειρίζονται και ελέγχουν την πρόσβαση των διεργασιών/νημάτων σε διαμοιραζόμενους πόρους, εξασφαλίζοντας την προστασία των διαμοιραζόμενων πόρων και την αξιοπιστία της επεξεργασίας τους. Κοινό χαρακτηριστικό των μηχανισμών αποτελεί η αποτροπή σε περισσότερες από μια διεργασίες να προσπελάζουν κοινά δεδομένα την ίδια χρονική στιγμή, το οποίο αναφέρεται ως αμοιβαίος αποκλεισμός (mutual exclusion). Αυτό εξασφαλίζει ότι αν ο κώδικας μιας διεργασίας προσπελάζει και επεξεργάζεται κάποια κοινά δεδομένα, π.χ. μια κοινή μεταβλητή ή αρχείο, όλες οι υπόλοιπες διεργασίες θα αποκλείονται από την εκτέλεση του δικού τους κώδικα που προσπελάζει και επεξεργάζεται αυτά τα κοινά δεδομένα. Το τμήμα του κώδικα σε μια διεργασία, από το οποίο γίνεται η προσπέλαση της κοινής μνήμης και της επεξεργασίας των κοινών δεδομένων εκεί, ονομάζεται κρίσιμο τμήμα (critical section).

Συμπερασματικά, όταν ένας αριθμός από Ν διεργασίες εκτελούνται ταυτόχρονα και επιθυμούν να χρησιμοποιήσουν κάποια κοινά δεδομένα, αυτό σημαίνει ότι κάθε μια από αυτές διαθέτει ένα κρίσιμο τμήμα στον κώδικά της από το οποίο προσπελάζει και επεξεργάζεται τα κοινά δεδομένα. Συνεπώς, για την αποτροπή των προβλημάτων από τις καταστάσεις συναγωνισμού κ.α. κατά την πρόσβαση στα κοινά δεδομένα, οι διεργασίες στα κρίσιμα τμήματά τους θα πρέπει να συγχρονίζονται (process synchronization). Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Κρίσιμο Τμήμα (critical section) Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Σημείωση: Ο προγραμματιστής θα πρέπει να επιδιώκει τη μείωση του χρόνου εκτέλεσης του κρίσιμου τμήματος, καθώς αυτό θα αυξήσει τον ταυτοχρονισμό, αφού θα μειωθεί ο χρόνος που περιμένουν οι υπόλοιπες διεργασίες/νήματα, και συνεπώς στη μονάδα του χρόνου περισσότερες θα εισέλθουν στο δικό τους κρίσιμο τμήμα και θα το εκτελέσουν.

Πηγή εικόνας: http://www.wikiwand.com/en/synchronization_(computer_science)

Ορισμένοι από τους μηχανισμούς που εξασφαλίζουν τον συγχρονισμό των διεργασιών είναι γνωστοί ως: semaphores, mutexes, conditions. Η υλοποίηση αυτών των μεθόδων αποτελεί τμήμα κώδικα (συναρτήσεων) που ελέγχει την πρόσβαση στα κοινά δεδομένα, την δέσμευση (κώδικας εισόδου) και αποδέσμευση (κώδικας εξόδου) αυτών, και ο οποίος εμπερικλείει το κρίσιμο τμήμα της εκάστοτε διεργασίας που συγχρονίζεται. Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Κρίσιμο Τμήμα (critical section) Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Κώδικας Εισόδου (entry code) Κώδικας Εξόδου (exit code) Σημείωση: Ο προγραμματιστής θα πρέπει να επιδιώκει τη μείωση των περιπτώσεων συγχρονισμού, καθώς ο συγχρονισμός σε αρκετές περιπτώσεις απαιτεί περισσότερο χρόνο από τον υπολογισμό που επιδιώκεται (synchronization takes more time than computation, especially in distributed computing).

Απαιτήσεις της λύσης του κρίσιμου τμήματος Όλοι οι μηχανισμοί για να παρέχουν αξιόπιστη λύση στο πρόβλημα του συγχρονισμού της πρόσβασης σε κοινούς/διαμοιραζόμενους πόρους, θα πρέπει να ικανοποιούν (υλοποιούν) τις κάτωθι προϋποθέσεις: Αμοιβαίος αποκλεισμός (mutual exclusion): αν μια διεργασία εκτελεί κώδικα στο κρίσιμο τμήμα της, τότε καμία άλλη διεργασία δεν εκτελεί κώδικα στο κρίσιμο τμήμα της. Πρόοδος (progress): αν δεν υπάρχει διεργασία που να βρίσκεται μέσα στο κρίσιμο τμήμα της και υπάρχουν διεργασίες που επιθυμούν να εισέλθουν στο κρίσιμο τμήμα τους, τότε η επιλογή της επόμενης διεργασίας που θα εισέλθει στο κρίσιμο τμήμα της δεν μπορεί να αναβάλλεται επ αόριστο. Στην απόφαση αυτή μπλοκαρίσματος δεν μπορούν να συμμετέχουν διεργασίες που δεν βρίσκονται στο κρίσιμο τμήμα τους. Πεπερασμένη Αναμονή (bounded waiting): πρέπει να υπάρχει ένα όριο στο πλήθος των φορών που επιτρέπεται σε άλλες διεργασίες να εισέλθουν στο κρίσιμο τμήμα τους, αφότου μια διεργασία έχει εκδώσει αίτηση να εισέλθει στο κρίσιμο τμήμα της και μέχρι η αίτηση αυτή να ικανοποιηθεί.

Αμοιβαίος αποκλεισμός Αμοιβαίος αποκλεισμός (mutual exclusion) 17

Υλοποιήσεις του αμοιβαίου αποκλεισμού Μερικές από τις προσεγγίσεις υλοποίησης του αμοιβαίου αποκλεισμού είναι οι ακόλουθες: Με απενεργοποίηση των διακοπών (disabling interrupts) Με αυστηρή εναλλαγή περιμένοντας σε ένα βρόγχο (busy waiting) Με την εντολή TSL (Test and Set Lock) Η λύση του Peterson 18

Με απενεργοποίηση των διακοπών (disabling interrupts) Κάθε διεργασία που εισέρχεται στο κρίσιμο τμήμα της να απενεργοποιεί όλες τις διακοπές και να τις επανεργοποιεί με την έξοδό της. Έτσι θα μπορεί ανενόχλητη να εκτελέσει το κρίσιμο τμήμα της, χωρίς να μπορεί να διακοπεί από τις υπόλοιπες, οι οποίες αναγκαστικά θα περιμένουν. Καθόλου δόκιμη λύση, καθώς και μη αποτελεσματική σε ένα πολυεπεξεργαστικό/πολυπύρηνο σύστημα, όπου η απενεργοποίηση των διακοπών της μιας CPU δεν εμποδίζει τις άλλες να παρεμβαίνουν στις λειτουργίες που εκτελεί η πρώτη CPU. 19

Με αυστηρή εναλλαγή περιμένοντας σε ένα βρόγχο (busy waiting) Κάθε διεργασία ελέγχει συνεχώς (κλειδώνει σε) μια μεταβλητή (ενεργός αναμονή ή αναμονή με απασχόληση, busy waiting) έως ότου αυτή πάρει συγκεκριμένη τιμή που θα την επιτρέψει να εισέλθει στο κρίσιμο τμήμα της. Διεργασία 0 Διεργασία 1

Αυτός ο τρόπος (ενεργός αναμονή) σπαταλά κύκλους της CPU (τους οποίους θα μπορούσε να αξιοποιήσει κάποια άλλη διεργασία), οπότε και είναι δόκιμος όταν η αναμονή θα είναι σύντομη*. Ειδάλλως χρησιμοποιούνται άλλες μέθοδοι, όπως π.χ. σημαφόροι, οι οποίοι όπως θα δούμε στη συνέχεια, επιτυγχάνουν τον αμοιβαίο αποκλεισμό χωρίς ενεργό αναμονή (π.χ. ο πυρήνας του Linux χρησιμοποιεί συνδυασμό τους). Η τεχνική αυτή αναφέρεται και ως περιστροφικό κλείδωμα (spinlock) καθώς η διεργασία φέρεται ως να «περιστρέφεται» ( spins ) (δηλ. εκτελείται σε ένα βρόγχο) περιμένοντας την αποδέσμευση της μεταβλητής κλειδώματος (lock). (*) Κατά την ενεργό αναμονή μιας διεργασίας σε ένα κλείδωμα, παραμένει φορτωμένη, οπότε είναι πλεονέκτημα ότι δεν απαιτείται εναλλαγή περιβάλλοντος λειτουργίας (που απαιτεί κάποιο χρόνο), άρα είναι χρήσιμη όταν τα κλειδώματα αναμένεται να κρατηθούν για μικρό χρονικό διάστημα (π.χ. της τάξης λιγότερων των δυο εναλλαγών περιβάλλοντος).

Με την εντολή TSL (Test and Set Lock) Η CPU (διεργασία) που εκτελεί αυτή την εντολή κλειδώνει το δίαυλο μνήμης ώστε να αποτρέψει την προσπέλαση μιας κοινόχρηστης μεταβλητής lock στη μνήμη από άλλες CPU (διεργασίες), μέχρι να τελειώσει την εργασία της. Η κοινόχρηστη μεταβλητή lock συμβάλλει στον συντονισμό των προσβάσεων στην κοινόχρηστη μνήμη. Όταν έχει την τιμή 0, οποιαδήποτε διεργασία μπορεί να της δώσει την τιμή 1 χρησιμοποιώντας την εντολή TSL και μετά να διαβάσει ή να γράψει στην κοινόχρηστη μνήμη. Όταν τελειώσει η διεργασία της ξαναδίνει την τιμή 0. 22

Η λύση του Peterson 23

Σημαφόροι ή Σηματοφόροι (Semaphores) Η σημαφόρος είναι ένας μηχανισμός συγχρονισμού που επιτυγχάνει τον αμοιβαίο αποκλεισμό των διεργασιών που επιθυμούν να εισέλθουν στο κρίσιμο τμήμα τους, χωρίς να απαιτεί ενεργό αναμονή της διεργασίας εκτελώντας κάποιες εντολές σε βρόγχο. Στη μέθοδο αυτή, η διεργασία που είναι εξαναγκασμένη να περιμένει, αναστέλλεται η εκτέλεσή της (wait) (αναστέλλεται, μπλοκάρεται, μεταβαίνει σε κατάσταση αναμονής ή αλλιώς σε λήθαργο), και επανέρχεται (ειδοποιείται για να προσπαθήσει να εισέλθει στο κρίσιμο τμήμα της) όταν κάποια άλλη διεργασία ολοκληρώσει και στη συνέχεια εκτελέσει μια λειτουργία αφύπνισης (signal). Μια μεταβλητή τύπου s (σημαφόρος) προσδιορίζει το πλήθος των σημάτων (αιτημάτων) των διεργασιών/νημάτων που επιθυμούν να εισέλθουν στην κρίσιμη περιοχή τους. 24

Η λειτουργία της αναστολής (wait) τοποθετεί τη διεργασία σε μια ουρά αναμονής (waiting queue) (λίστα με δείκτες προς το PCB της κάθε διεργασίας) που συσχετίζεται με τη μεταβλητή της σημαφόρου (s), και η διεργασία μεταβαίνει σε κατάσταση αναμονής. Στη συνέχεια ο έλεγχος μεταφέρεται στον χρονοπρογραμματιστή της ΚΜΕ, ο οποίος επιλέγει μια άλλη διεργασία για εκτέλεση. Μια διεργασία που είναι μπλοκαρισμένη, περιμένοντας σε ένα σημαφόρο, θα επανεκκινηθεί (σε κατάσταση ετοιμότητας) (ready queue) όταν κάποια άλλη διεργασία ολοκληρώσει και στη συνέχεια εκτελέσει μια λειτουργία αφύπνισης (signal). Ο χρονοπρογραμματιστής της ΚΜΕ μπορεί να μεταβεί ή να μη μεταβεί από την εκτελούμενη διεργασία στη διεργασία που μόλις έγινε έτοιμη, ανάλογα με τον αλγόριθμο χρονοπρογραμματισμού. 25

Συνοψίζοντας, μια μεταβλητή σημαφόρος s μπορεί να προσπελαστεί μέσω δύο ατομικών (χωρίς διακοπή) ή αδιαίρετων* πράξεων: wait - αναστολής ή μπλοκαρίσματος της διεργασίας (ή down, αύξησης της σημαφόρου), και signal - αφύπνισης ή ξεμπλοκαρίσματος της διεργασίας (ή up, μείωσης της σημαφόρου). Πηγή εικόνας: www.keil.com/pack/doc/cmsis/rtos/html/group CMSIS RTOS SemaphoreMgmt.html (*) Αδιαίρετων: δηλ. όταν μια διεργασία τροποποιεί (wait/signal) την τιμή της σημαφόρου, καμία άλλη διεργασία δεν μπορεί να τροποποιήσει την τιμή της ίδιας σημαφόρου ταυτόχρονα. 26

Μπορεί να θεωρηθεί πως οι παραπάνω λειτουργίες ορίζονται ως εξής: void wait(int *s) { void signal(int *s) { while (*s<=0) {} *s++; } *s--; } Παράδειγμα: υλοποίηση κρίσιμου τμήματος για n διεργασίες με σημαφόρο: shared vars: semaphore s=1; process body: while (1) { wait(s); do_critical_section(); signal(s); } 27

Παράδειγμα υλοποίησης σημαφόρου typedef struct { int sval; /* η τιμή της σημαφόρου */ struct procq pq; /* ουρά διεργασιών που αναμένουν στη σημαφόρο */ } semaphore; /* για να εισέλθουν στο κρίσιμο τμήμα τους */ void init(semaphore *s, int val) { s->sval=val; initq(s->pq); } void wait(semaphore *s) { s->sval--; if (s->sval<0) { addq(s->pq,thisprocess()); suspend(); } } void signal(semaphore *s) { s->sval++; if (s->sval<==0) { resume(rmvq(s->pq)); } } 28

Δυαδικοί σημαφόροι (binary semaphores) ή Mutexes Η τιμή μιας δυαδικής σημαφόρου μπορεί να παίρνει τις τιμές 0 και 1. Αυτές είναι γνωστοί και ως κλειδώματα αμοιβαίου αποκλεισμού (mutual exclusion locks ή mutex locks). Τα mutexes επιτρέπουν ή απαγορεύουν την πρόσβαση σε μια κρίσιμη περιοχή. Έτσι χρησιμοποιούνται αποκλειστικά στη διαχείριση του αμοιβαίου αποκλεισμού που εφαρμόζεται σε κάποιο κοινόχρηστο πόρο. Η διεργασία/νήμα που κάνει πρόσβαση στην κρίσιμη περιοχή καλεί τη mutex_lock και κλειδώνει το mutex (θέτει την τιμή 0), ενώ αποχωρώντας για να το ξεκλειδώσει καλεί τη mutex_unlock (θέτει την τιμή 1). 29

Παραδείγματα κλήσεων της POSIX Thread library Pthread με mutexes για το συγχρονισμό νημάτων pthread_mutex_lock() - acquire a lock on the specified mutex variable. If the mutex is already locked by another thread, this call will block the calling thread until the mutex is unlocked. pthread_mutex_unlock() - unlock a mutex variable. An error is returned if mutex is already unlocked or owned by another thread. pthread_mutex_trylock() - attempt to lock a mutex or will return error code if busy. Useful for preventing deadlock conditions. 30

Παράδειγμα χρήσης των mutexes (της Pthread) για το συγχρονισμό νημάτων Πηγή: www.yolinux.com/tutorials/linuxtutorialposixthreads.html 31

thread.c gcc thread.c lpthread./a.out

thread.cpp g++ thread.cpp lpthread./a.out

Κλασικά προβλήματα συγχρονισμού Το πρόβλημα της αποθήκης πεπερασμένης χωρητικότητας (bounded-buffer problem) Το πρόβλημα αναγνωστών και εγγραφέων (readers and writers problem) Το πρόβλημα των συνδαιτυμόνων φιλοσόφων (dining philosophers problem) 34

Αποθήκη πεπερασμένης χωρητικότητας semaphore mutex,full,empty; /* Κοινά δεδομένα */ init(&mutex,1); init(&empty,n); init(&full,0); /* Αρχικοποίηση */ /* διεργασία παραγωγός producer */ while (1) { παραγωγή αντικειμένου item wait(&empty); wait(&mutex); προσθήκη αντικειμένου item στην αποθήκευση signal(&mutex); signal(&full); } /* διεργασία καταναλωτής consumer */ while (1) { wait(&full); wait(&mutex); απομάκρυνση αντικειμένου item από την αποθήκευση signal(&mutex); signal(&empty); κατανάλωση αντικειμένου item } Ενημερωτική διαφάνεια

Αναγνώστες και εγγραφείς semaphore mutex,write; int readers; /* Κοινά δεδομένα */ init(&mutex,1); init(&write,1); readers=0; /* Αρχικοποίηση */ /* διεργασία εγγραφέας -writer */ while (1) { wait(&write); γράψιμο δεδομένων signal(&write); } /* διεργασία αναγνώστης -reader */ while (1) { wait(&mutex); readers++; if (readers==1) {wait(&write);} signal(&mutex); διάβασμα δεδομένων wait(&mutex); readers--; if (readers==0) {signal(write);} signal(&mutex); } Ενημερωτική διαφάνεια

Οι συνδαιτυμόνες φιλόσοφοι semaphore fork[n]; /*Κοινά δεδομένα */ init(&fork[0],1); /* Αρχικοποίηση */ init(&fork[1],1); init(&fork[n-1],1); /* Ο φιλόσοφος i */ while (1) { wait(&fork[i]); wait(&fork[(i+1)%n); επιτέλους τρώμε! signal(&fork[i]); signal(&fork[(i+1)%n]); ας σκεφτούμε λιγάκι } Οι φιλόσοφοι τρώνε/σκέφτονται Για να φάνε χρειάζονται 2 πηρούνια Παίρνουν ένα πηρούνι τη φορά Πώς να αποφύγουμε το αδιέξοδο (deadlock); Ενημερωτική διαφάνεια

Ελεγκτές ή Παρακολουθητές (Monitors) Δομή που επιτρέπει την ασφαλή πρόσβαση σε δεδομένα μεταξύ ταυτόχρονων διεργασιών. Σε ένα ελεγκτή την κάθε χρονική στιγμή μια μόνο διεργασία μπορεί να είναι ενεργή. monitor monitor-name { δηλώσεις κοινών μεταβλητών procedure P1 ( ) { } procedure P2 ( ) { } procedure Pn ( ) { } { κώδικας αρχικοποίησης } } Οι ρουτίνες πρόσβασης Pi εκτελούνται συγχρονισμένα, με εγγυημένο τον αμοιβαίο αποκλεισμό ανάμεσα σε διεργασίες. Ο ελεγκτής υποστηρίζει τον συγχρονισμό με τη χρήση μεταβλητών συνθήκης (condition variables). 38

Για να επιτραπεί σε μια διεργασία να περιμένει μέσα σε έναν ελεγκτή, πρέπει να δηλωθεί αντίστοιχη μεταβλητή συνθήκης (condition variable): condition x; Μπορεί να χρησιμοποιηθεί με τις λειτουργίες wait και signal. Η λειτουργία x.wait() σημαίνει ότι η διεργασία αναστέλλεται. Η λειτουργία x.signal() εκκινεί (μόνο) μια από τις διεργασίες που έχουν ανασταλεί, αν υπάρχει (διαφορετικά δεν κάνει τίποτα). Η λειτουργία x.signalall() εκκινεί όλες τις διεργασίες (αν υπάρχουν) που έχουν ανασταλεί μέσω της μεταβλητής x. Αναμονή υπό συνθήκη (conditional wait): x.wait(c); c ακέραιος που ελέγχεται όταν εκτελείται η λειτουργία wait. Η τιμή του c (αριθμός προτεραιότητας) αποθηκεύεται με το όνομα της διεργασίας που ανεστάλη. Η εκτέλεση της x.signal, ενεργοποιεί τη διεργασία με τη μικρότερη προτεραιότητα. 39

Δομή του ελεγκτή 40

Σχηματική θεώρηση ελεγκτή Ελεγκτής Ελεγκτής με μεταβλητές συνθήκης 41

Παραδείγματα κλήσεων της POSIX Thread library Pthread με conditions για το συγχρονισμό νημάτων 42

Πηγή: https://randu.org/tutorials/threads/ Ενημερωτική διαφάνεια

Υλοποίηση ελεγκτών με σημαφόρους Για κάθε ελεγκτή, καθολικές μεταβλητές: semaphore mutex,next; int next-count; Επιπλέον, για κάθε μεταβλητή συνθήκης, μεταβλητές: semaphore x-sem; int x-count; Αρχικοποίηση του ελεγκτή: init(&mutex,1); init(&next,0); next-count=0; Και αρχικοποίηση για κάθε μεταβλητή συνθήκης: init(&x-sem); x-count=0; Για κάθε ρουτίνα πρόσβασης Pi, το σώμα της αντικαθίσταται με : procedure Pi ( ) { wait(&mutex); κυρίως σώμα της Pi if (next-count > 0) {signal(&next);} else {signal(&mutex);} } Ενημερωτική διαφάνεια

Η λειτουργία x.wait() μπορεί να υλοποιηθεί ως εξής: x-count++; if (next-count > 0) { signal(&next); } else { signal(&mutex); } wait(&x-sem); x-count--; Η λειτουργία x.signal() μπορεί να υλοποιηθεί ως εξής: if (x-count > 0) { next-count++; signal(&x-sem); wait(&next); next-count--; } Η λειτουργία x.signalall() μπορεί να υλοποιηθεί ως εξής: if (x-count > 0) { next-count++; for (c=x-count; c > 0; c--) { signal(&x-sem); } wait(&next); next-count--; } Ενημερωτική διαφάνεια

POSIX Thread (related) functions Πηγή: www.yolinux.com/tutorials/linuxtutorialposixthreads.html Ενημερωτική διαφάνεια

Διαδιεργασιακή επικοινωνία (Inter-Process Communication, IPC) Όταν οι διεργασίες αλληλεπιδρούν μεταξύ τους πρέπει να συγχρονίζονται και να μπορούν να επικοινωνούν (για να ανταλλάσσουν πληροφορίες/δεδομένα). (α) Shared memory (διαμέσω κοινής ή διαμοιραζόμενης μνήμης) (β) Message passing (μηχανισμός μεταβίβασης ή περάσματος μηνυμάτων). Μεταβίβασης μηνυμάτων Μέσω κοινής μνήμης 48

(α) Διαμέσω κοινής (ή διαμοιραζόμενης) μνήμης (shared memory) Σε ένα πολυπεξεργαστικό/πολυπύρηνο σύστημα σε ένα υπολογιστή δύο ή περισσότεροι επεξεργαστές/πυρήνες μοιράζονται την πρόσβαση (ανάγνωση/εγγραφή) σε μια κοινή μνήμη. Οι διεργασίες επικοινωνούν προσδιορίζοντας ένα κοινό τμήμα/άρθρωμα μνήμης (shared buffer) (στο οποίο συγχρονίζονται με απλά locks, π.χ. mutexes) και αποκτώντας πρόσβαση σε αυτό (shared memory create και attach) στη συνέχεια να μπορούν να ανταλλάσσουν πληροφορίες διαβάζοντας και γράφοντας (load/store) δεδομένα σε αυτό. Έτσι σε αυτή την περίπτωση η μνήμη διασπάται σε πολλαπλά τμήματα ώστε να εξυπηρετούνται οι ταυτόχρονες προσπελάσεις σε αυτά από διαφορετικούς πυρήνες/διεργασίες (η κρυφή μνήμη συμβάλλει στη μείωση των προσπελάσεων της κύριας μνήμης). On shared memory platforms, the native compilers translate user program variables into actual memory addresses, which are global. Το δίκτυο διασύνδεσης είναι στην απλούστερη περίπτωση ο δίαυλος συστήματος (system bus), τον οποίο κάθε δεδομένη στιγμή μόνο ένας πυρήνας μπορεί να χρησιμοποιεί για επικοινωνία με κάποιο τμήμα μνήμης.

(β) Μοντέλο μεταβίβασης μηνυμάτων (message-passing model) Το μοντέλο μεταβίβασης μηνυμάτων παρέχει ένα μηχανισμό που επιτρέπει στις διεργασίες να επικοινωνούν και να συγχρονίζουν τις ενέργειές τους, ακόμα και όταν βρίσκονται σε διαφορετικά υπολογιστικά συστήματα συνδεδεμένα μέσω δικτύου. Οι διεργασίες που θέλουν να επικοινωνήσουν (συνήθως bi-directional) θα πρέπει να έχουν ένα τρόπο να αναφέρονται η μια στην άλλη: (1) Άμεσα (direct communication), ή (2) Έμμεσα (indirect communication) Χρησιμοποιούνται δύο θεμελιώδεις εντολές/λειτουργίες: send και receive. P1 Message Passing P2 Message Passing Interface (MPI) is the industry standard for message passing. http://www.mcs.anl.gov/research/projects/mpi/

(1) Στην άμεση επικοινωνία έχουμε: send (διεργασία-παραλήπτης, μήνυμα), και receive (διεργασία-αποστολέας, μήνυμα) Η μία διεργασία στέλνει ένα μήνυμα με την εντολή send, σε μια άλλη διεργασία, το οποίο και παραλαμβάνει με την εντολή receive στον δικό της ιδιωτικό χώρο (local memory) (link μεταξύ δυο διεργασιών μόνο). (2) Στην έμμεση επικοινωνία έχουμε: send (γραμματοθυρίδα, μήνυμα), και receive (γραμματοθυρίδα, μήνυμα) Η μία διεργασία στέλνει ένα μήνυμα με την εντολή send, σε ένα ενταμιευτή ή γραμματοθυρίδα μηνυμάτων (message buffer/queue, mailbox, port), το οποίο λαμβάνει η άλλη με την εντολή receive. Η χρήση του ενταμιευτή είναι διαμοιραζόμενη (shared) οπότε αποτελεί κρίσιμη περιοχή και για αυτό πρέπει να ισχύουν κάποιοι κανόνες συγχρονισμού των διεργασιών. Μια θυρίδα μπορεί να είναι προσβάσιμη από πολλές διεργασίες, όμως συνήθως το μήνυμα το παραλαμβάνει η διεργασία που «πρώτη» το επιχειρεί. Ουσιαστικά επιτρέπεται στο σύστημα να διαλέξει αυθαίρετα τον παραλήπτη. Όμως ο αποστολέας ειδοποιείται για τον παραλήπτη.

Η μεταβίβαση μηνυμάτων έχει το πλεονέκτημα ότι μπορεί να υλοποιηθεί τόσο σε (α) κατανεμημένα συστήματα, όσο και σε (β) συστήματα πολλαπλών επεξεργαστών/πυρήνων ή (γ) μονού επεξεργαστή κοινής/διαμοιραζόμενης μνήμης (shared memory). Έτσι ο μηχανισμός είναι ιδιαίτερα χρήσιμος και στα κατανεμημένα περιβάλλοντα (distributed memory systems), όπου οι διεργασίες που επικοινωνούν μπορεί να βρίσκονται σε διαφορετικούς υπολογιστές συνδεδεμένοι μέσω δικτύου. Προβλήματα: communication overhead, difficulty of programming.

Inter-process communication approaches Πηγή: https://en.wikipedia.org/wiki/inter-process_communication Ενημερωτική διαφάνεια

Ερωτήσεις Περιγράψτε τα προβλήματα συγχρονισμού της πρόσβασης σε κοινά δεδομένα. Περιγράψτε τι είναι το κρίσιμο τμήμα και τις απαιτήσεις της λύσης του κρίσιμου τμήματος (προϋποθέσεις συγχρονισμού της πρόσβασης σε κοινούς/διαμοιραζόμενους πόρους). Περιγράψτε τι είναι ο αμοιβαίος αποκλεισμός καθώς και τη μέθοδο υλοποίησής του «με αυστηρή εναλλαγή περιμένοντας σε ένα βρόγχο (busy waiting)». Τι γνωρίζετε για τις σημαφόρους; Τι γνωρίζετε για τους ελεγκτές ή παρακολουθητές; Τι γνωρίζετε για τη διαδιεργασιακή επικοινωνία διαμέσω κοινής (ή διαμοιραζόμενης) μνήμης (shared memory); Τι γνωρίζετε για τη διαδιεργασιακή επικοινωνία μεταβίβασης μηνυμάτων (message-passing); 54