Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

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

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "Νήματα Εκτέλεσης – Συγχρονισμός Διεργασιών σε Κοινή Μνήμη."— Μεταγράφημα παρουσίασης:

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

2 Για τη δημιουργία των διαφανειών έχει χρησιμοποιηθεί υλικό από τις διαφάνειες παραδόσεων που βασίζονται στο βιβλίο, Silberschatz, Galvin and Gagne, “Operating Systems Concepts”, 6 th Edition. Οι διαφάνειες αυτές βρίσκονται στο δικτυακό τόπο:

3 Νήματα Εκτέλεσης (Threads)

4 Σελίδα 4 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Εισαγωγή — Επισκόπηση — Μοντέλα πολλαπλών νημάτων (Multithreading Models) — Θέματα νημάτων (Threading Issues) — Pthreads και νήματα σε μερικά δημοφιλή ΛΣ

5 Σελίδα 5 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Η Έννοια της Διεργασίας (και) Γιατί οι Διεργασίες δεν είναι Αρκετές — Η διεργασία είναι κυρίως μια λογική έννοια, η οποία στην πράξη υλοποιείται με τον μηχανισμό της διεργασίας σε επίπεδο ΛΣ. Μια λογική διεργασία μπορεί να αντιστοιχεί σε μια (ή περισσότερες) διεργασίες του ΛΣ — Τι γίνεται όμως αν μια λογική διεργασία χρειάζεται να υποστηρίξει «ταυτόχρονη» εκτέλεση κώδικα; — Μπορεί να δημιουργηθούν πολλές διεργασίες (ΛΣ) που συνεργάζονται για τον κοινό σκοπό (της λογικής διεργασίας) — Όμως ακόμα και αν οι διεργασίες δημιουργηθούν έτσι ώστε να επικοινωνούν (αποδοτικά) μέσω κοινής μνήμης, το σύστημα επιβαρύνεται λόγω των επιπρόσθετων εναλλαγών περιβάλλοντος λειτουργίας (context switch) που πραγματοποιούνται

6 Σελίδα 6 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα — Τα νήματα (νήματα ελέγχου), ονομάζονται και ελαφρές διεργασίες (lightweight processes – LWPs), είναι ξεχωριστές ροές του ίδιου προγράμματος που εκτελούνται μέσα σε μια λογική διεργασία — Τα νήματα μιας διεργασίας ανήκουν πάντα στον ίδιο χρήστη — Λειτουργούν (στην ουσία) όπως και οι διεργασίες, δεν είναι όμως πραγματικά ανεξάρτητες εκτελέσεις, καθώς:  έχουν τα ίδια δικαιώματα πρόσβασης σε πόρους  μοιράζονται τους ίδιους πόρους (δεδομένα, κώδικα, ανοικτά αρχεία, σήματα, … ακόμα και τον χρόνο της ΚΜΕ)  μοιράζονται την ίδια μνήμη!

7 Σελίδα 7 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Thread Switch vs Context Switch — Για κάθε νήμα διατηρείται ξεχωριστή κατάσταση εκτέλεσης, δηλαδή μετρητής προγράμματος, τιμές των καταχωρητών και στοίβα — Η εναλλαγή μεταξύ νημάτων (thread switch) ισοδυναμεί στην πράξη με απλή εναλλαγή κατάστασης ΚΜΕ (register set switch) και όχι με πραγματική εναλλαγή περιβάλλοντος λειτουργίας (context switch) — Κατά το thread switch δεν πραγματοποιούνται λειτουργίες διαχείρισης μνήμης και δικαιωμάτων πρόσβασης, με αποτέλεσμα το thread switch να είναι πολύ πιο γρήγορο από το context switch

8 Σελίδα 8 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασίες και Νήματα

9 Σελίδα 9 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Πλεονεκτήματα Χρήσης Νημάτων (αντί Συνεργαζομένων Διεργασιών) — Απόκριση / απόδοση συστήματος — Διαμοιρασμός πόρων (Resource Sharing) — Οικονομία πόρων — Εκμετάλλευση αρχιτεκτονικών πολλαπλών επεξεργαστών Πρόβλημα: — Έλεγχος συγχρονισμού (concurrency control problems)

10 Σελίδα 10 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Νημάτων σε Επίπεδο Χρήστη (User Threads) — Η διαχείριση των νημάτων γίνεται από βιβλιοθήκες που εκτελούνται σε κατάσταση χρήστη (user mode). Αποφεύγεται η επικοινωνία με το σύστημα/πυρήνα (δεν πραγματοποιούνται κλήσεις συστήματος) — Τα νήματα εκτελούνται μέσα από μια κοινή διεργασία — Ένα νήμα αφήνει την ΚΜΕ με κλήση της ρουτίνας εναλλαγής, με λειτουργία που προκαλεί έμμεσα εναλλαγή ή με την λήξη ενός μετρητή — Συνήθως δεν υποστηρίζεται κατανομή του χρόνου εκτέλεσης της διεργασίας στα διάφορα νήματα που έχει μέσα της — Παραδείγματα: POSIX pthreads, Mach C-threads, Solaris threads

11 Σελίδα 11 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα σε Επίπεδο Χρήστη (συνέχεια) Πλεονεκτήματα: — Τα νήματα χρήστη εναλλάσσονται (θεωρητικά) γρηγορότερα από τα νήματα πυρήνα. Ωστόσο, στην πράξη, καλές υλοποιήσεις νημάτων σε επίπεδο πυρήνα [Linux] εναλλάσσονται με συναφή απόδοση Μειονεκτήματα: — Ένα νήμα μπορεί να μονοπωλήσει τον χρόνο εκτέλεσης μιας διεργασίας (λιμοκτονία (starvation) των υπολοίπων νημάτων) — Δεν γίνεται εκμετάλλευση της συμμετρικής πολυεπεξεργασίας — Όταν μπλοκαριστεί ένα νήμα μέσα σε κάποια λειτουργία Ι/Ο τότε μπλοκάρονται όλα τα νήματα που εκτελούνται μέσα στην ίδια διεργασία (γιατί το ΛΣ δεν «γνωρίζει» την ύπαρξη τους)

12 Σελίδα 12 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Νημάτων σε Επίπεδο Συστήματος/Πυρήνα (Kernel Threads) — Τα νήματα πυρήνα υλοποιούνται στον πυρήνα του ΛΣ, και οι αντίστοιχες βιβλιοθήκες χρησιμοποιούν κλήσεις συστήματος — Σε αυτή την περίπτωση ο πυρήνας χρονοδρομολογεί κάθε νήμα εντός της μονάδας χρόνου που αναλογεί στην διεργασία μέσα στην οποία εκτελούνται τα νήματα — Υπάρχει περισσότερος φόρτος στο σύστημα λόγω της εναλλαγής κατάστασης χρήστη σύστημα (user mode system mode) και την διαχείριση πιο πολύπλοκων περιβαλλόντων, αλλά οι αρχικές μετρήσεις απόδοσης δείχνουν αμελητέα αύξηση στο χρόνο — Παραδείγματα: Windows 95/98/NT/2000, Solaris,Tru64 UNIX, BeOS, Linux

13 Σελίδα 13 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα σε Επίπεδο Πυρήνα (συνέχεια) Πλεονεκτήματα: — Αποτροπή της μονοπώλησης της μονάδας χρόνου μιας διεργασίας από ένα νήμα (ενώ υπάρχουν και άλλα προς εκτέλεση) — Το μπλοκάρισμα ενός νήματος σε Ι/Ο δεν συνεπάγεται μπλοκάρισμα και των άλλων νημάτων που εκτελούνται μέσα στην ίδια διεργασία — Μια διεργασία μπορεί να εκμεταλλευτεί (πιο εύκολα) τη συμμετρική πολυεπεξεργασία του ΛΣ και να τρέχει γρηγορότερα με κάθε ΚΜΕ που προστίθεται στο σύστημα Μειονεκτήματα: — Ταχύτητα εναλλαγής νημάτων

14 Σελίδα 14 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Μοντέλα Πολλαπλών Νημάτων (Multithreading Models) — Ανάλογα με το αν το ΛΣ υποστηρίζει νήματα σε επίπεδο πυρήνα αλλά και το πως αυτά αντιστοιχίζονται σε νήματα επιπέδου χρήστη, υπάρχουν διάφορες προσεγγίσεις υλοποίησης:  Πολλά σε Ένα (Many-to-One)  Ένα προς Ένα (One-to-One)  Πολλά προς Πολλά (Many-to-Many)

15 Σελίδα 15 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Πολλά σε Ένα (Many-to-One) — Πολλά νήματα επιπέδου χρήστη αντιστοιχούν σε ένα νήμα πυρήνα — Χρησιμοποιείται σε συστήματα που δεν υποστηρίζουν νήματα πυρήνα

16 Σελίδα 16 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Μοντέλο Πολλά σε Ένα

17 Σελίδα 17 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ένα προς Ένα (One-to-One) — Κάθε νήμα χρήστη αντιστοιχεί σε ένα νήμα πυρήνα — Παραδείγματα: - Windows 95/98/NT/ OS/2

18 Σελίδα 18 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Μοντέλο Ένα προς Ένα

19 Σελίδα 19 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Μοντέλο Πολλά προς Πολλά — Επιτρέπει σε πολλά νήματα χρήστη να αντιστοιχιστούν σε πολλά νήματα πυρήνα — Επιτρέπει στο ΛΣ να δημιουργήσει επαρκή αριθμό νημάτων πυρήνα — Solaris 2 — Windows NT/2000 με το πακέτο ThreadFiber

20 Σελίδα 20 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Μοντέλο Πολλά προς Πολλά (συνέχεια)

21 Σελίδα 21 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Θέματα Νημάτων (Threading Issues) — Σημασιολογία των κλήσεων συστήματος fork() και exec() — Δεξαμενές νημάτων (Thread pools) — Ακύρωση νημάτων (Thread cancellation) — Χειρισμός σημάτων (Signal handling) — Δεδομένα σχετικά με τα νήματα (Thread specific data)

22 Σελίδα 22 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Pthreads (POSIX Threads) — Μια τυποποίηση POSIX (IEEE c) API για δημιουργία και συγχρονισμό νημάτων σε περιβάλλον Unix — To API προσδιορίζει τους τύπους (types), τις επικεφαλίδες των ρουτινών (interfaces), και την συμπεριφορά των ρουτινών της αντίστοιχης βιβλιοθήκης — Η υλοποίηση της βιβλιοθήκης εναπόκειται στο ΛΣ

23 Σελίδα 23 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα στο Solaris 2

24 Σελίδα 24 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασίες στο Solaris 2

25 Σελίδα 25 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα στα Windows 2000 — Υλοποιούν την αντιστοίχηση «Ένα προς Ένα» — Κάθε νήμα περιέχει:  ένα thread id  ένα σύνολο από καταχωρητές (register set)  ξεχωριστές στοίβες για το χρήστη και τον πυρήνα  ιδιωτικό χώρο αποθήκευσης δεδομένων

26 Σελίδα 26 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα στο Linux (Linux Threads) — To Linux αναφέρεται σε αυτά ως εργασίες (tasks) παρά ως νήματα — Η δημιουργία νημάτων γίνεται μέσω της κλήσης συστήματος clone() — H Clone() επιτρέπει σε μια εργασία παιδί να μοιράζεται το χώρο διευθύνσεων της πατρικής εργασίας (διεργασίας)

27 Σελίδα 27 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Νήματα στην Java — Τα νήματα στη Java μπορούν να δημιουργηθούν μέσω:  Επέκτασης του Thread class  Υλοποίησης της διεπαφής Runnable — Την διαχείριση των νημάτων στη Java αναλαμβάνει η JVM

28 Σελίδα 28 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Κατάσταση Νημάτων στην Java

29 Συγχρονισμός Διεργασιών σε Κοινή Μνήμη (Process Synchronization)

30 Σελίδα 30 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Εισαγωγή — Θεωρητικό υπόβαθρο — Το πρόβλημα του κρίσιμου τμήματος (the critical-section problem) — Υλικό συγχρονισμού — Σηματοφορείς ή σημαφόροι (semaphores) — Κλασικά προβλήματα συγχρονισμού — Κρίσιμες περιοχές (critical regions) — Ελεγκτές/παρακολουθητές (monitors)

31 Σελίδα 31 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Θεωρητικό Υπόβαθρο — Η ταυτόχρονη πρόσβαση σε κοινά δεδομένα μπορεί να οδηγήσει σε ασυνέπεια δεδομένων (data inconsistency) — Το πρόβλημα της συνέπειας υφίσταται στα νήματα και στις διεργασίες(*) με κοινή μνήμη που έχουν ταυτόχρονη πρόσβαση σε όλες τις καθολικές μεταβλητές και τα δυναμικά δεδομένα ενός προγράμματος — Παρόμοιο πρόβλημα αντιμετωπίζει ο κώδικας του συστήματος του οποίου η εκτέλεση μπορεί να διακοπεί από τις ρουτίνες χειρισμού διακοπών (interrupt handlers) που με την σειρά τους μπορεί να κάνουν κλήσεις συστήματος (που και αυτές μπορεί να διακοπούν...) — (*) Σε αυτή την ενότητα χρησιμοποιούμε τον (γενικότερο) όρο διεργασία, ακόμα και όταν αναφερόμαστε σε νήματα

32 Σελίδα 32 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Πρόσβαση σε Κοινή Μεταβλητή (Shared variable) Έστω πως δύο διεργασίες εκτελούν τον παρακάτω κώδικα: int i=0; /* κοινή μεταβλητή */ void body { i++; } — Ποιά η τιμή της μεταβλητής i αφού εκτελεσθούν οι διεργασίες;  Μπορεί να είναι 1 ή 2, δεν το ξέρουμε εκ των προτέρων!  Κάθε εκτέλεση μπορεί να δίνει διαφορετικό αποτέλεσμα!

33 Σελίδα 33 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Γιατί; — Το πρόβλημα είναι πως η εκτέλεση της εντολής i++ δεν είναι (εγγυημένα) ατομική (atomic) δηλαδή χωρίς να υπάρχει πιθανότητα διακοπής της — Η εντολή i++ μεταφράζεται σε γλώσσα μηχανής ως εξής: regX = mem[i_adr]; regX = regX+1; memy[i_adr] = regX; — Η σειριακή εκτέλεση του κώδικα των διεργασιών δίνει διαφορετικό αποτέλεσμα από μια διαπλεκόμενη (interleaved) εκτέλεσή του — Η εκτέλεση εξαρτάται από την (τυχαία) χρονοδρομολόγηση του ΛΣ

34 Σελίδα 34 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Σενάρια Εκτέλεσης Αρχικά η μεταβλητή i έχει την τιμή 0. Σενάριο Α 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 Σενάριο B 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

35 Σελίδα 35 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Κατάσταση Συναγωνισμού (Race Condition) — Κατάσταση Συναγωνισμού: Η κατάσταση όπου πολλές διεργασίες προσπελαύνουν και χειρίζονται ταυτόχρονα κοινά δεδομένα — Η τελική τιμή των κοινών δεδομένων εξαρτάται από το πως θα δρομολογηθεί η επιμέρους εκτέλεσης του κώδικα των διεργασιών — Για την αποτροπή καταστάσεων συναγωνισμού, οι διεργασίες με κοινή μνήμη πρέπει να συγχρονίζονται

36 Σελίδα 36 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Το Πρόβλημα του Κρίσιμου Τμήματος (critical section problem) — Ένας αριθμός από Ν διεργασίες εκτελούνται ταυτόχρονα μεταξύ τους και επιθυμούν να χρησιμοποιήσουν κάποια κοινά δεδομένα — Κάθε διεργασία έχει ένα τμήμα κώδικα που καλείται κρίσιμο τμήμα (critical section), στο οποίο προσπελαύνονται τα κοινά δεδομένα Πρόβλημα: Διασφάλισε ότι όταν μια διεργασία εκτελεί κώδικα στο κρίσιμο τμήμα της, καμία άλλη διεργασία δεν θα να εκτελέσει στο κρίσιμο τμήμα της

37 Σελίδα 37 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αφηρημένη Δομή των Διεργασιών while (1) { Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Κρίσιμο Τμήμα (critical section) Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) }

38 Σελίδα 38 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Οι 3 Απαιτήσεις της Λύσης του Κρίσιμου Τμήματος 1.Αμοιβαίος αποκλεισμός (mutual exclusion): Αν η μια διεργασία εκτελεί κώδικα στο κρίσιμο τμήμα της, τότε καμία άλλη διεργασία δεν εκτελεί κώδικα στο κρίσιμο τμήμα της 2.Πρόοδος (progress): Αν δεν υπάρχει διεργασία που να βρίσκεται μέσα στο κρίσιμο τμήμα της και υπάρχουν διεργασίες που επιθυμούν να εισέλθουν στο κρίσιμο τμήμα τους, τότε η επιλογή της επόμενης διεργασίας που θα εισέλθει στο κρίσιμο τμήμα της δεν μπορεί να αναβάλλεται επ’ αόριστον

39 Σελίδα 39 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Οι 3 Απαιτήσεις της Λύσης του Κρίσιμου Τμήματος (συνέχεια) 3.Πεπερασμένη Αναμονή (bounded waiting): Πρέπει να υπάρχει ένα όριο στο πλήθος των φορών που επιτρέπεται σε άλλες διεργασίες να εισέλθουν στο κρίσιμο τμήμα τους, αφότου μια διεργασία έχει εκδώσει αίτηση να εισέλθει στο κρίσιμο τμήμα της και μέχρι η αίτηση αυτή να ικανοποιηθεί  Υποθέτουμε ότι κάθε διεργασία εκτελείται με μη μηδενική ταχύτητα  Δεν μπορεί να γίνει καμία υπόθεση η οποία να αφορά τη σχετική ταχύτητα των διαφόρων διεργασιών, ή το πλήθος των επεξεργαστών στους οποίους εκτελούνται οι διεργασίες

40 Σελίδα 40 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Πιο Λεπτομερής Δομή των Διεργασιών while (1) { Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) Κρίσιμο Τμήμα (critical section) Κανονικός Κώδικας (δεν τίθεται θέμα συγχρονισμού) } Κώδικας Εισόδου (entry code) Κώδικας Εξόδου (exit code)

41 Σελίδα 41 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος 1 (δύο Διεργασίες) — Κοινή μεταβλητή turn (η διεργασία P i εισέρχεται στο ΚΤ μόνο όταν turn=i ): shared vars: int turn=0; process body: while (1) { while (turn!=i) {} /* entry code */ do_critical_section(); turn=(i+1)%2; /* exit code */ } — Ικανοποιεί τον αμοιβαίο αποκλεισμό, αλλά όχι την πρόοδο (γιατί;)

42 Σελίδα 42 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος 2 (δύο Διεργασίες) — Κοινή μεταβλητή boolean flag[2] (η διεργασία P i εισέρχεται στο ΚΤ μόνο όταν flag[i]= true ): shared vars: boolean flag[2]={false,false}; process body: while (1) { flag[i]=true; /* entry code */ while (flag[(i+1)%2]) {} do_critical_section(); flag[i]=false; /* exit code */ } — Ικανοποιεί τον αμοιβαίο αποκλεισμό, αλλά όχι την πρόοδο (γιατί;)

43 Σελίδα 43 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος 3 (δύο Διεργασίες) — Συνδυασμός των δύο προηγουμένων αλγορίθμων: shared vars: int turn=0; boolean flag[2]={false,false}; process body: while (1) { flag[i]=true; turn=(i+1)%2; /* entry code */ while ( (flag[(i+1)%2]) && (turn=(i+1)%2) ) {} do_critical_section(); flag[i]=false; /* exit code */ } — Ικανοποιεί και τις τρεις απαιτήσεις (γιατί;)

44 Σελίδα 44 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος για πολλές Διεργασίες Ο Αλγόριθμος Bakery — Πριν την είσοδό της στο κρίσιμο τμήμα, μια διεργασία P i λαμβάνει έναν αριθμό σειράς t i. Το σύστημα αριθμοδότησης δημιουργεί αριθμούς σειράς με αύξουσα σειρά αρίθμησης, π.χ., 1,2,3,3,3,4,5… — Η διεργασία με τον μικρότερο αριθμό σειράς εισέρχεται στο κρίσιμο τμήμα — Αν οι διεργασίες P i και P j έχουν τον ίδιο αριθμό σειράς, αν i < j, τότε εξυπηρετείται πρώτα η P i, αλλιώς πρώτα η P j — Συμβολισμοί:  (a,b) before (c,d) ((a < c) || ((a = c) && (b < d))  max (a 0,…, a n-1 ) = k, k  a i για i = 0,…, n – 1

45 Σελίδα 45 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ο Αλγόριθμος Bakery (συνέχεια) shared vars: boolean choosing[n]={false,…,false}; int t[n]={0,…,0}; process body: while (1) { choosing[i] = true; t[i] = max(t[0],t[1],…, t[n-1])+1; choosing[i] = false; for (j=0; j

46 Σελίδα 46 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλικό Συγχρονισμού (Synchronization Hardware) — Μερικοί επεξεργαστές υποστηρίζουν την εξής εντολή TestAndSet για τον ατομικό έλεγχο και αλλαγή μιας θέσης μνήμης (μεταβλητής) — Η συμβολική υλοποίηση της εντολής δίνεται ως εξής: boolean TestAndSet(boolean *target) { boolean value_read = *target; *target = true; return value_read; } — Η εντολή εκτελείται χωρίς διακοπή (εγγυημένα)

47 Σελίδα 47 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος Κρίσιμου Τμήματος με Χρήση της TestandSet shared vars: boolean lock=false; process body: while (1) { while (TestAndSet(&lock)) {} do_critical_section(); lock = false; }

48 Σελίδα 48 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλικό Συγχρονισμού (συνέχεια) — Εξατομικευμένη εναλλαγή δύο μεταβλητών void Swap(boolean *a, boolean *b) { boolean tmp; tmp = *a; *a = *b; *b = tmp; }

49 Σελίδα 49 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αλγόριθμος Κρίσιμου Τμήματος με Χρήση της Swap shared vars: boolean lock=false; process body: boolean key; while (1) { key=true; do {Swap(&lock,&key);} while (key); do_critical_section(); lock = false; }

50 Σελίδα 50 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Σημαφόροι ή Σηματοφορείς (Semaphores) — Εργαλείο συγχρονισμού που δεν απαιτεί ενεργό αναμονή (busy waiting) της διεργασίας, εκτελώντας κάποιες εντολές σε βρόγχο — Μια μεταβλητή τύπου s σηματοφορέα μπορεί να προσπελαστεί μέσω δύο ατομικών πράξεων wait (ή down) και signal (ή up), που μπορεί να θεωρηθεί πως υλοποιούνται ως εξής: void wait(int *s) { while (*s<=0) {} *s--; } void signal(int *s) { *s++; }

51 Σελίδα 51 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Κρίσιμου Τμήματος για n Διεργασίες με Σημαφόρους shared vars: semaphore s=1; process body: while (1) { wait(s); do_critical_section(); signal(s); }

52 Σελίδα 52 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Σημαφόρου typedef struct { int sval; /* value of semaphore */ struct procQ pq;/* queue of waiting processes */ } semaphore; void init(semaphore *s, int val) { s->sval=val; initQ(s->pq); }

53 Σελίδα 53 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Σημαφόρου (συνέχεια) 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)); }

54 Σελίδα 54 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Η Σημαφόρος ως ένα Γενικό Εργαλείο Συγχρονισμού Διεργασία P i Διεργασία P j… A wait(flag) signal(flag) B… — Χρήση της σημαφόρου flag με αρχική τιμή 0 — Εκτέλεση του B στην P j μόνο αφού εκτελεστεί το A στην P i

55 Σελίδα 55 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Τύποι Σημαφόρων — Γενική σημαφόρος (ή σημαφόρος μετρητής) (general or counting semaphore) – μπορεί να έχει μια οποιαδήποτε ακέραια τιμή — Δυαδική σημαφόρος (binary semaphore) – μπορεί να παίρνει τιμές μόνο μεταξύ 0 και 1, κάτι που μπορεί να σημαίνει ευκολότερη υλοποίηση — Μια γενική σημαφόρος μπορεί να υλοποιηθεί με χρήση δυαδικών σημαφόρων

56 Σελίδα 56 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Γενικής Σημαφόρου με Δυαδικές Σημαφόρους typedef struct { bin_semaphore s1,s2; int cnt; } semaphore; void init(semaphore *s, int val) { bin_init(&s->s1,1); bin_init(&s->s2,0); s->cnt=val; }

57 Σελίδα 57 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Γενικής Σημαφόρου με Δυαδικές Σημαφόρους (συνέχεια) void wait(semaphore *s) { bin_wait(&s->s1); s->cnt--; if (s->cnt<0) { bin_signal(&s->s1); bin_wait(&s->s2); } bin_signal(&s->s1); } void signal(semaphore *s) { bin_wait(&s->s1); s->cnt++; if (s->cnt s2);} else {bin_signal(&s->s1);} }

58 Σελίδα 58 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Κλασικά Προβλήματα Συγχρονισμού — Το πρόβλημα της αποθήκης πεπερασμένης χωρητικότητας (bounded-buffer problem) — Το πρόβλημα αναγνωστών και εγγραφέων (readers and writers problem) — Το πρόβλημα των συνδαιτυμόνων φιλοσόφων (dining philosophers problem)

59 Σελίδα 59 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αποθήκη Πεπερασμένης Χωρητικότητας Κοινά δεδομένα: semaphore mutex,full,empty; Αρχικοποίηση: init(&mutex,1); init(&empty,n); init(&full,0);

60 Σελίδα 60 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασία Παραγωγός (producer) while (1) { … παραγωγή αντικειμένου item wait(&empty); wait(&mutex); προσθήκη αντικειμένου item στην αποθήκευση signal(&mutex); signal(&full); … }

61 Σελίδα 61 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασία Καταναλωτής (consumer) while (1) { … wait(&full); wait(&mutex); απομάκρυνση αντικειμένου item από την αποθήκευση signal(&mutex); signal(&empty); κατανάλωση αντικειμένου item … }

62 Σελίδα 62 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αναγνώστες και Εγγραφείς Κοινά δεδομένα: semaphore mutex,write; int readers; Αρχικοποίηση: init(&mutex,1); init(&write,1); readers=0;

63 Σελίδα 63 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασία Εγγραφέας while (1) { … wait(&write); γράψιμο δεδομένων signal(&write); … }

64 Σελίδα 64 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Διεργασία Αναγνώστης while (1) { … wait(&mutex); readers++; if (readers==1) {wait(&write);} signal(&mutex); διάβασμα δεδομένων wait(&mutex); readers--; if (readers==0) {signal(&write);} signal(&mutex); … }

65 Σελίδα 65 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Οι Συνδαιτυμόνες Φιλόσοφοι Κοινά δεδομένα: semaphore fork[n]; Αρχικοποίηση: init(&fork[0],1); init(&fork[1],1); … init(&fork[n-1],1);

66 Σελίδα 66 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ο Φιλόσοφος i while (1) { … wait(&fork[i]); wait(&fork[(i+1)%n); επιτέλους τρώμε! signal(&fork[i]); signal(&fork[(i+1)%n]); ας σκεφτούμε λιγάκι … } — Υπάρχει περίπτωση ο ένας φιλόσοφος να περιμένει τον άλλο σε κύκλο;

67 Σελίδα 67 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Κρίσιμες Περιοχές (Critical Regions) — Δομή υψηλού επιπέδου για την υποστήριξη του συγχρονισμού κρίσιμων τμημάτων, ως εξής: — Μια κοινή μεταβλητή v τύπου T ορίζεται ως: T (shared) v; — Η v μπορεί να προσπελαστεί μόνο μέσω της εντολής region : region v when B do S; όπου η διεργασία ελέγχει την συνθήκη B και αν είναι αληθής, τότε εκτελεί την ομάδα εντολών S, διαφορετικά ανατέλλεται μέχρι η συνθήκη B να γίνει αληθής. — Τόσο ο έλεγχος της συνθήκης B όσο και η εκτέλεση της ομάδας εντολών S γίνεται ατομικά (το σύστημα εγγυάται πως δεν παρεμβάλλονται άλλες διεργασίες σε αυτή την περιοχή).

68 Σελίδα 68 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αποθήκη Πεπερασμένης Χωρητικότητας με Κρίσιμες Περιοχές typedef struct { item slots[n]; int in,out,cnt; } buffer; buffer (shared) b; b.cnt=0; b.in=b.out=0; slots[0] slots[n-1] direction of in, out

69 Σελίδα 69 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αποθήκη Πεπερασμένης Χωρητικότητας (συνέχεια) Διεργασία Παραγωγός while (1) { … item=produce(); region b when (b.cnt0) { item=b.slots[b.out]; b.out=(b.out+1)%n; b.cnt--; } consume(item); … }

70 Σελίδα 70 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση της Δομής region με Σημαφόρους — Συσχετισμός με την κρίσιμη περιοχή, των ακόλουθων μεταβλητών: semaphore mx, q1, q2; int n1, n2; — Η αμοιβαίως αποκλειόμενη πρόσβαση στο κρίσιμο τμήμα παρέχεται από τη mx — Αν μια διεργασία δεν μπορεί να εισέλθει στην κρίσιμη περιοχή λόγω του ότι η συνθήκη B είναι ψευδής, αρχικά περιμένει στη σημαφόρο q1, και μετά στη σημαφόρο q2 πριν μπορέσει να επανεξετάσει την τιμή της Β. Καταγραφή του πλήθους των διεργασιών που περιμένουν στις q1 και q2, γίνεται με τη n1 και τη n2 — Υποθέτουμε διάταξη FIFO στην αναμονή των διεργασιών για μια σημαφόρο

71 Σελίδα 71 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Δομής region (συνέχεια) typedef struct { semaphore mx,q1,q2; int n1,n2; } region; void init(region *r) { init(&r->mx,1); init(&r->q1,0); init(&r->q2,0); n1=n2=0; }

72 Σελίδα 72 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Δομής region (συνέχεια) void enter(region *r, Condition B, Code S) { wait(&r->mx); while (!B) { r->n1++; if (r->n2>0) {signal(&r->q2);} else {signal(&r->mx);} wait(&r->q1); r->n1--; r->n2++; if (r->n1>0){signal(&r->q1);} else {signal(&r->q2);} wait(&r->q2); r->n2--; } S; if (r->n1>0) {signal(&r->q1);} else if (r->n2>0) {signal(&r->q2);} else {signal(&r->mx);} }

73 Σελίδα 73 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ελεγκτές/Παρακολουθητές (Monitors) — Δομή υψηλού επιπέδου που επιτρέπει την ασφαλή πρόσβαση ενός αφηρημένου τύπου δεδομένων μεταξύ ταυτόχρονων διεργασιών monitor monitor-name { δηλώσεις κοινών μεταβλητών procedure P1 (…) {…} procedure P2 (…) {…} procedure Pn (…) {…} { κώδικας αρχικοποίησης } — Οι ρουτίνες πρόσβασης Pi εκτελούνται συγχρονισμένα, με εγγυημένο τον αμοιβαίο αποκλεισμό ανάμεσα σε διεργασίες

74 Σελίδα 74 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ελεγκτές/Παρακολουθητές (συνέχεια) — Για να επιτραπεί σε μια διεργασία να περιμένει μέσα σε έναν ελεγκτή, πρέπει να δηλωθεί αντίστοιχη μεταβλητή συνθήκης (condition variable): condition x; — Μπορεί να χρησιμοποιηθεί μόνο με τις λειτουργίες wait και signal  Η λειτουργία x.wait() σημαίνει ότι η διεργασία αναστέλλεται  Η λειτουργία x.signal() εκκινεί (μόνο) μια από τις διεργασίες που έχουν ανασταλεί, αν υπάρχει (διαφορετικά δεν κάνει τίποτα)  Η λειτουργία x.signalAll() εκκινεί όλες τις διεργασίες (αν υπάρχουν) που έχουν ανασταλεί μέσω της μεταβλητής x

75 Σελίδα 75 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αναμονή με Προτεραιότητες — Αναμονή υπό συνθήκη (conditional-wait): x.wait(c);  c – ακέραιος που ελέγχεται όταν εκτελείται η λειτουργία wait  Η τιμή του c (αριθμός προτεραιότητας) αποθηκεύεται με το όνομα της διεργασίας που ανεστάλη  Η εκτέλεση της x.signal, ενεργοποιεί τη διεργασία με τη μικρότερη προτεραιότητα

76 Σελίδα 76 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Σχηματική Θεώρηση ενός Ελεγκτή

77 Σελίδα 77 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Ελεγκτής με Μεταβλητές Συνθήκης

78 Σελίδα 78 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Συνδαιτυμόνες Φιλόσοφοι με Ελεγκτή monitor dining_phils { enum {thinking,hungry,eating} state[n]; condition self[n]; void pickup(int i); void putdown(int i); void test(int i); void init() { int i; for (i=0; i<5; i++) {state[i] = thinking;} }

79 Σελίδα 79 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Συνδαιτυμόνες Φιλόσοφοι (συνέχεια) void pickup(int i) { state[i] = hungry; test[i]; if (state[i] != eating) { self[i].wait(); } void putdown(int i) { state[i] = thinking; test((i+n-1)%n); /* test left */ test((i+1)%n); /* test right */ }

80 Σελίδα 80 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Συνδαιτυμόνες Φιλόσοφοι (συνέχεια) void test(int i) { if ( (state[i] == hungry) && (state[(i+n-1)%n] != eating) && (state[(i+1)%n] != eating) ) { state[i] = eating; self[i].signal(); }

81 Σελίδα 81 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Ελεγκτών με Σημαφόρους — Για κάθε ελεγκτή, καθολικές μεταβλητές: 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;

82 Σελίδα 82 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Ελεγκτών με Σημαφόρους (συνέχεια) — Για κάθε ρουτίνα πρόσβασης Pi, το σώμα της αντικαθίσταται με : procedure Pi (…) { wait(&mutex); κυρίως σώμα της Pi if (next-count > 0) {signal(&next);} else {signal(&mutex);} }

83 Σελίδα 83 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Ελεγκτών με Σημαφόρους (συνέχεια) — Η λειτουργία x.wait() μπορεί να υλοποιηθεί ως εξής: x-count++; if (next-count > 0) { signal(&next); } else { signal(&mutex); } wait(&x-sem); x-count--;

84 Σελίδα 84 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Ελεγκτών με Σημαφόρους (συνέχεια) — Η λειτουργία x.signal() μπορεί να υλοποιηθεί ως εξής: if (x-count > 0) { next-count++; signal(&x-sem); wait(&next); next-count--; }

85 Σελίδα 85 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Υλοποίηση Ελεγκτών με Σημαφόρους (συνέχεια) — Η λειτουργία x.signalAll() μπορεί να υλοποιηθεί ως εξής: if (x-count > 0) { next-count++; for (c=x-count; c > 0; c--) { signal(&x-sem); } wait(&next); next-count--; }

86 Σελίδα 86 ΝΗΜΑΤΑ & ΣΥΓΧΡΟΝΙΣΜΟΣ Αδιέξοδο και Λιμοκτονία (Deadlock and Starvation) — Αδιέξοδο – δύο ή περισσότερες διεργασίες περιμένουν απεριόριστα για ένα γεγονός που μπορεί να προκληθεί μόνο από μια από τις δυο — Έστω S και Q δύο σημαφόροι με αρχική τιμή 1 P 0 P 1 wait(S);wait(Q); wait(Q);wait(S);   signal(S);signal(Q); signal(Q)signal(S); — Λιμοκτονία – απεριόριστη αναμονή. Μια διεργασία μπορεί να μην φύγει από την ουρά της σημαφόρου στην οποία έχει ανασταλεί


Κατέβασμα ppt "Νήματα Εκτέλεσης – Συγχρονισμός Διεργασιών σε Κοινή Μνήμη."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google