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

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

CSLab National Technical University of Athens

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

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

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

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

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

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

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

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

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

NIKOΛΑΟΣ ΝΤΙΡΛΗΣ 5ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΑΙΘΟΥΣΑ Β4

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

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

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

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

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

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

Διεργασίες και Νήματα (2/2)

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

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

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ. Διεργασίες και Νήματα Εργαστηριακές Ασκήσεις

ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ & ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΧΕΙΜΕΡΙΝΟ ΕΞΑΜΗΝΟ ΜΑΘΗΜΑ: ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ

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

ΝΗΜΑΤΑ - ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

Παράλληλη Επεξεργασία Κεφάλαιο 5 Μοίρασμα Δεδομένων

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

Εκφωνήσεις ασκήσεων εργαστηρίου 2 (pthreads)

Αρχιτεκτονική Υπολογιστών

Λειτουργικά Συστήματα 7ο εξάμηνο, Ακαδημαϊκό Έτος

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

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

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

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

3 η ΑΣΚΗΣΗ. Προηγμένα Θέματα Αρχιτεκτονικής Υπολογιστών

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

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

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

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

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

Συγχρονισμός. Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων

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

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

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

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

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

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

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

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

Αδιέξοδα (Deadlocks)

Λειτουργικά Συστήματα 7ο εξάμηνο, Ακαδημαϊκό Έτος

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

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

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

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

Υ- 07 Παράλληλα Συστήματα Transac9onal memory

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

Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Σχολή Τεχνολογικών Εφαρμογών Ακαδημαϊκό έτος

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

Συστήματα Παράλληλης και Κατανεμημένης Επεξεργασίας

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

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

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

Εργαστήριο 4: Υλοποίηση Αφηρημένου Τύπου Δεδομένων: Ταξινομημένη Λίστα

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εισαγωγή στον Προγραμματισμό

ΙΩΑΝΝΗΣ ΚΩΝΣΤΑΝΤΙΝΟΥ 2ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΠΑΡΑΣΚΕΥΗ 26 ΟΚΤΩΒΡΙΟΥ 2012 ΑΙΘΟΥΣΑ Β4

Συγχρονισµός: Αδιέξοδο & Παρατεταµένη Στέρηση

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

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

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

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

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

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

Λειτουργικά Συστήματα 7ο εξάμηνο, Ακαδημαϊκή περίοδος

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Εισαγωγή εκτελέσιμου κώδικα σε διεργασίες

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

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

Κατανεμημένα και Παράλληλα Συστήματα (εργαστήριο) Παραδείγματα με openmp

Transcript:

Συγχρονισμός Συστήματα Παράλληλης Επεξεργασίας 9ο εξάμηνο ΣΗΜΜΥ ακ. έτος 2009-2010 CSLab National Technical University of Athens Κορνήλιος Κούρτης kkourt@cslab.ece.ntua.gr Εργαστήριο Υπολογιστικών Συστημάτων ΕΜΠ Δεκέμβριος 2009

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

1 επεξεργαστής. Δ0 p0-ins0 p0-ins1. p0-ins2.... Δ1 p1-ins0 p1-ins1 p1-ins2.... Δ2 p2-ins0 p2-ins1 p2-ins2....χρονοδρομολογητής. KME p2-ins0 p2-ins1 p0-ins0 p1-ins0...

>1 επεξεργαστές. Δ0 p0-ins0 p0-ins1. p0-ins2.... Δ1 p1-ins0 p1-ins1 p1-ins2.... Δ2 p2-ins0 p2-ins1 p2-ins2....χρονοδρομολογητής. ΚΜΕ0. $. ΚΜΕ1. $.Μνήμη

Πρόσβαση σε μοιραζόμενες δομές δεδομένων Πιθανή δημιουργία ασυνεπειών - Διακοπτή χρονοδρομολόγηση (preemptive scheduling) Ο χρονοδρομολογητής μπορεί να διακόψει την τρέχουσα διεργασία σε οποιοδήποτε σημείο. - Πολυεπεξεργασία (συστήματα μοιραζόμενης μνήμης) Ταυτόχρονη πρόσβαση σε κοινές δομές δεδομένων (μοντέλο συνέπειας μνήμης). Ανάγκη για συγχρονισμό διεργασιών

Παράδειγμα: Διπλά συνδεδεμένη λίστα struct list_head { struct list_head *next; struct list_head *prev; }; list_del(prev, next) { prev->next = next; next->prev = prev; }..A.B.C.D

Παράδειγμα: Διπλά συνδεδεμένη λίστα struct list_head { struct list_head *next; struct list_head *prev; }; list_del(prev, next) { prev->next = next; next->prev = prev; } Διαγραφή C (1 διεργασία) 1. t0: prev->next = next; 2. t0: next->prev = prev; 3. OK!..A.B.C.D..A.B.C.D..A.B.C.D

Παράδειγμα: Διπλά συνδεδεμένη λίστα struct list_head { struct list_head *next; struct list_head *prev; }; list_del(prev, next) { prev->next = next; next->prev = prev; } Διαγραφή C,D (2 διεργασίες) 1. t0: prev->next = next; 2. t1: prev->next = next;..a.b.c.d..a.b.c.d..a.b.c.d

Παράδειγμα: Διπλά συνδεδεμένη λίστα struct list_head { struct list_head *next; struct list_head *prev; }; list_del(prev, next) { prev->next = next; next->prev = prev; } Διαγραφή C,D (2 διεργασίες) 1. t0: prev->next = next; 2. t1: prev->next = next; 3. ΑΣΥΝΕΠΕΙΑ..A.B.C.D..A.B.C.D..A.B.C.D

Παράδειγμα: Παραγωγός-Καταναλωτής δομή: Κυκλικός πίνακας (μεγέθους N) Καταναλωτής: προσθέτει δεδομένα Παραγωγός: αφαιρεί δεδομένα #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0;

Παράδειγμα: Παραγωγός-Καταναλωτής δομή: Κυκλικός πίνακας (μεγέθους N) Καταναλωτής: προσθέτει δεδομένα Παραγωγός: αφαιρεί δεδομένα #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; void enqueue(item_t item){ while (count == N) ; // wait buffer[in] = item; in = NEXT(in); count++; } item_t dequeue(void){ item_t item; while (count == 0) ; // wait item = buffer[out]; out = NEXT(out); count--; return item }

Παράδειγμα: Παραγωγός-Καταναλωτής δομή: Κυκλικός πίνακας (μεγέθους N) Καταναλωτής: προσθέτει δεδομένα Παραγωγός: αφαιρεί δεδομένα #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; void enqueue(item_t item){ while (count == N) ; // wait buffer[in] = item; in = NEXT(in); count++; } item_t dequeue(void){ item_t item; while (count == 0) ; // wait item = buffer[out]; out = NEXT(out); count--; return item }

Κατάσταση συναγωνισμού race condition t count++ count-- 1 LOAD r, count 2 ADD 1, r 3 LOAD r, count 4 SUB 1, r 5 STORE r, count 6 STORE r, count

Κατάσταση συναγωνισμού race condition t count++ count-- 1 LOAD r, count 2 ADD 1, r 3 LOAD r, count 4 SUB 1, r 5 STORE r, count 6 STORE r, count Αν για t = 0, count = c, τότε για t = 7, count = c 1 Ασυνέπεια στη δομή του κυκλικού πίνακα Κατάσταση συναγωνισμού: κατάσταση κατά την οποία το αποτέλεσμα ενός υπολογισμού εξαρτάται από τη σειρά που πραγματοποιούνται οι προσπελάσεις.

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

Τακτικές αμοιβαίου αποκλεισμού Ενεργός Αναμονή (busy-wait) Καταναλώνει υπολογιστικούς πόρους, όσο μια άλλη διεργασία βρίσκεται στο κρίσιμο τμήμα. Η ΚΜΕ μπορεί να χρησιμοποιηθεί για άλλες εργασίες Κατανάλωση ενέργειας Αμοιβαίος αποκλεισμός με αναστολή εκτέλεσης Αν το ΚΤ είναι κατειλημμένο η διεργασία αναστέλλει την λειτουργία της και τίθεται υπό αναμονή Ο επεξεργαστής ελευθερώνεται και ο Χρονοδρομολογητής επιλέγει άλλη διεργασία. Κατά την έξοδο από το ΚΤ, ενεργοποιείται μια υπό αναμονή διεργασία

Κλειδώματα Locks Ορισμός κρίσιμων τμημάτων: Είσοδος στο ΚΤ: κλείδωμα (lock) Έξοδος από το ΚΤ: ξεκλείδωμα (unlock) do { lock(mylock); critical section unlock(mylock); remainder section } while (TRUE);

Κλειδώματα Locks Ορισμός κρίσιμων τμημάτων: Είσοδος στο ΚΤ: κλείδωμα (lock) Έξοδος από το ΚΤ: ξεκλείδωμα (unlock) do { lock(mylock); critical section unlock(mylock); remainder section } while (TRUE); do { lock(mylock); other critical section unlock(mylock); other remainder section } while (TRUE);

Μια πρώτη λύση στο πρόβλημα του συγχρονισμού για 2 διεργασίες flag = { FALSE, FALSE }; do { flag[me] = TRUE; while (flag[other]) ; critical section flag[me] = FALSE; remainder section } while (TRUE);

Μια πρώτη λύση στο πρόβλημα του συγχρονισμού για 2 διεργασίες flag = { FALSE, FALSE }; do { flag[me] = TRUE; while (flag[other]) ; critical section flag[me] = FALSE; remainder section } while (TRUE); t me=0 me=1 1 flag[0] = TRUE 2 flag[1] = TRUE

Μια πρώτη λύση στο πρόβλημα του συγχρονισμού για 2 διεργασίες flag = { FALSE, FALSE }; do { flag[me] = TRUE; while (flag[other]) ; critical section flag[me] = FALSE; remainder section } while (TRUE); t me=0 me=1 1 flag[0] = TRUE 2 flag[1] = TRUE Αδιέξοδο!

Ζητήματα Υλοποίησης Ο μεταγλωττιστής μπορεί να αναδιατάξει τις εντολές Ο Επεξεργαστής μπορεί να εκτελέσει εντολές εκτός σειράς (Out of Order Execution) Σε πολυεπεξεργαστικά συστήματα μοιραζόμενης μνήμης, δεν είναι προφανές πότε θα φανούν οι αλλαγές που έκανε ένας επεξεργαστής σε μια θέση μνήμης στους υπόλοιπους (συνέπεια μνήμης).

Μηχανισμοί Συγχρονισμού Ατομικές εντολές (Atomic Operations) Φράγματα μνήμης (Memory Barriers) Περιστροφικά Κλειδώματα (Spinlocks) Κλειδώματα αμοιβαίου αποκλεισμού (Mutexes) Σημαφόροι (Semaphores) Ελεγκτές/Παρακολουθητές (Monitors)

Ατομικές Εντολές Atomic Operations Εγγυημένες να λειτουργούν ατομικά Υλοποιούνται στο υλικό Χρησιμοποιούνται για τη δημιουργία μηχανισμών συγχρονισμού Παραδείγματα: TestAndSet: Θέτει την τιμή μιας μεταβλητής σε TRUE και επιστρέφει την προηγούμενη τιμή. Swap: Ανταλλάσσει την τιμή δύο μεταβλητών. FetchAndOp: Πραγματοποιεί μια πράξη στην τιμή μιας μεταβλητής και επιστρέφει την προηγούμενη τιμή.

Συνέπεια μνήμης memory consistency Μοντέλο συνέπειας μνήμης: Κανόνες που σέβεται το σύστημα και επιτρέπουν στον προγραμματιστή να προβλέψει τη συμπεριφορά του, όταν τους ακολουθεί. Σε αντίθεση με τη συνάφεια, αφορά > 1 θέσεις μνήμης Αφορά το πότε είναι ορατή μια αλλαγή Εξαρτάται από την υποκείμενη αρχιτεκτονική (υλικού ή λογισμικού) Παραδείγματα: strict consistency sequential consistency processor consistency

Sequential consistency Υπάρχει ολική διάταξη στις εντολές πρόσβασης μνήμης των επεξεργαστών Τα αποτελέσματα των εντολών σέβονται την διάταξη Η διάταξη των εντολών ενός επεξεργαστή διατηρείται στην ολική διάταξη Η ύπαρξη της ολικής διάταξης δεν συνπέγεται ότι αυτή είναι γνωστή στον χρόνο εκτέλεσης

Φράγματα μνήμης memory barriers Στην πράξη τα συστήματα πολλαπλών επεξεργαστών δεν υλοποιούν το μοντέλο Sequential Consistency Βελτιστοποίηση εντολών πρόσβασης στη μνήμη οδηγεί χαλαρά μοντέλα συνέπειας. Φράγματα μνήμης: Μηχανισμοί που επιβάλουν συγκεκριμένη σειρά στις προσβάσεις στη μνήμη πχ lfence, sfence, mfence εντολές σε x86 αρχιτεκτονικές Περισσότερες πληροφορίες: wikipedia: Memory barrier Memory Barriers: a Hardware View for Software Hackers (P. McKenney)

Spinlocks Υλοποίηση αμοιβαίου αποκλεισμού με: Ατομικές εντολές Βρόχους ενεργού αναμονής (busy-wait loops)

Spinlocks Υλοποίηση αμοιβαίου αποκλεισμού με: Ατομικές εντολές Βρόχους ενεργού αναμονής (busy-wait loops) Παραδείγματα: do { while (TestAndSet(lock)) ; critical section UnSet(lock); remainder section } while (TRUE);

Spinlocks Υλοποίηση αμοιβαίου αποκλεισμού με: Ατομικές εντολές Βρόχους ενεργού αναμονής (busy-wait loops) Παραδείγματα: do { while (TestAndSet(lock)) ; critical section UnSet(lock); remainder section } while (TRUE); do { key = TRUE; while (key) Swap(lock,key); critical section UnSet(lock); remainder section } while (TRUE);

Επίδοση spinlock Lock Contetion (συναγωνισμός) Ιδανικά η επίδοση ενός κλειδώματος είναι ανεξάρτητη από τον αριθμό των νημάτων που το διακδικούν Στη πράξη, όταν πολλά νήματα διεκδικούν το κλείδωμα δημιουργείται συναγωνισμός Παράδειγμα: H πράξη TestAndSet δημιουργεί κίνηση στον διάδρομο όταν πολλαπλά νήματα ανταγωνίζονται για το κλείδωμα. H κίνηση οδηγεί σε χρονικές καθυστερήσεις. - Χρονική υποχώρηση (backoff) - Test and TestAndSet - Ticket lock (μόνο ανάγνωση για απόκτηση lock) - Array-Based Lock (αναμονή σε διαφορετικές θέσεις μνήμης) do { while (TestAndSet(lock)) ; critical section UnSet(lock); remainder section } while (TRUE);

Test and TestAndSet (x86) spin_lock: 1: lock; decl [lock] # Atomically decreament lock jns 2f # If not negative jump to 2 (forward) 3: rep; nop # relax the processor cmpl $0, [lock] # compare lock with zero jle 3b # lock still less than zero jmp 1b # try again to get the lock 2: # got the lock spin_unlock: movl $1, [lock]

Ticket lock atomic_t now-serving = 0; atomic_t next-ticket = 0; lock: myticket = FetchAndInc(next-ticket); while (myticket!= now-serving) ; unlock: Inc(now-serving);

Array-based lock atomic_t spin-locations[p] = {LOCKED, LOCKED,...}; atomic_t next-location = 0; lock: myloc = FetchAndInc(next-location) % P; while (spin-locations[myloc] == LOCKED) ; unlock: Set(spin-locations[myloc], LOCKED); Set(spin-locations[myloc + 1 % P], UNLOCKED); Το πολύ P νήματα για το κλείδωμα Ζητήματα cache

Array-based lock atomic_t spin-locations[p] = {LOCKED, LOCKED,...}; atomic_t next-location = 0; lock: myloc = FetchAndInc(next-location) % P; while (spin-locations[myloc] == LOCKED) ; unlock: Set(spin-locations[myloc], LOCKED); Set(spin-locations[myloc + 1 % P], UNLOCKED); Το πολύ P νήματα για το κλείδωμα Ζητήματα cache false sharing

Σημαφόροι Semaphores Επινοήθηκαν από τον Dijkstra Λειτουργίες: Αρχικοποιείται σε μία ακέραιη τιμή. Μετά την αρχικοποίηση μόνο δύο λειτουργίες επιτρέπονται η wait() και η signal() wait(): Ο ακέραιος αριθμός μειώνεται. Αν γίνει αρνητικός τότε το νήμα σταματάει την λειτουργία του και περιμένει signal(): Ο ακέραιος αριθμός αυξάνεται. Αν υπάρχουν νήματα που περιμένουν, ένα από αυτά συνεχίζει την λειτουργία του

Σημαφόροι Σημειώσεις Μια διεργασία δεν μπορεί να ξέρει την τιμή του σημαφόρου και συγκεκριμένα δεν ξέρει αν θα χρειαστεί να περιμένει ή όχι σε περίπτωση που καλέσει την wait() Δεν υπάρχει κάποιος κανόνας για το ποιο νήμα, από αυτά που περιμένουν, θα συνεχίσει την λειτουργία του μετά από κλήση της signal() Ένα Mutex μπορεί να υλοποιηθεί με έναν σημαφόρο αρχικοποιημένο στο 1 (unlocked) Οι λειτουργίες στους σημαφόρους παραδοσιακά αναφέρονται και ως P() (wait()) και V() (signal()).

Πρόβλημα Παραγωγού-Καταναλωτή #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; void enqueue(item_t item){ item_t dequeue(void){ } while (count == N) ; // wait buffer[in] = item; in = NEXT(in); count++; } item_t item; while (count == 0) ; // wait item = buffer[out]; out = NEXT(out); count--; return item

Πρόβλημα Παραγωγού-Καταναλωτή #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; sema_t mutex = semaphore(1); void enqueue(item_t item){ wait(mutex); while (count == N) ; // wait buffer[in] = item; in = NEXT(in); count++; signal(mutex); } item_t dequeue(void){ wait(mutex); item_t item; while (count == 0) ; // wait item = buffer[out]; out = NEXT(out); count--; signal(mutex); return item }

Πρόβλημα Παραγωγού-Καταναλωτή #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; sema_t mutex = semaphore(1); void enqueue(item_t item){ wait(mutex); while (count == N) ; // wait buffer[in] = item; in = NEXT(in); count++; signal(mutex); } ΑΔΙΕΞΟΔΟ! (deadlock) item_t dequeue(void){ wait(mutex); item_t item; while (count == 0) ; // wait item = buffer[out]; out = NEXT(out); count--; signal(mutex); return item }

Πρόβλημα Παραγωγού-Καταναλωτή (Σωστή λύση) #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; sema_t mutex = semaphore(1); sema_t full = semaphore(0); sema_t empty = semaphore(n); void enqueue(item_t item){ buffer[in] = item; in = NEXT(in); count++; item_t dequeue(void){ item_t item; item = buffer[out]; out = NEXT(out); count--; } } return item

Πρόβλημα Παραγωγού-Καταναλωτή (Σωστή λύση) #define NEXT(x) ((x + 1) % N) item_t buffer[n]; int in=0, out=0, count=0; sema_t mutex = semaphore(1); sema_t full = semaphore(0); sema_t empty = semaphore(n); void enqueue(item_t item){ wait(empty); wait(mutex); buffer[in] = item; in = NEXT(in); count++; signal(mutex); signal(full); } item_t dequeue(void){ item_t item; wait(full); wait(mutex); item = buffer[out]; out = NEXT(out); count--; signal(mutex); signal(empty); return item }

Πρόβλημα Αναγνωστών - Εγγραφέων readers-writers problem Δύο κλάσεις προσβάσεων: Αναγνώστες: Δεν αλλάζουν τα δεδομένα Εγγραφείς: Αλλάζουν τα δεδομένα Κανόνες: Επιτρέπονται πολλαπλοί Αναγνώστες ταυτόχρονα Οι Εγγραφείς πρέπει να έχουν αποκλειστική πρόσβαση Χρησιμοποιείται για δομές που δεν αλλάζουν συχνά Προτεραιότητες: Οι εγγραφείς περιμένουν έως ότου δεν υπάρχουν αναγνώστες Οι αναγνώστες περιμένουν όταν κάποιος εγγραφέας είναι έτοιμος Πιθανή Λιμοκτονία (starvation) και στις δύο περιπτώσεις

Πρόβλημα Αναγνωστών - Εγγραφέων προτεραιότητα στους αναγνώστες sema_t mutex = semaphore(1); sema_t write = semaphore(1); int readcount = 0; read_lock: wait(mutex); if (++readcount == 1) wait(write); signal(mutex); write_lock: wait(write); write_unlock: signal(write); read_unlock: wait(mutex); if (--readcount == 0) signal(write); signal(mutex);

Το πρόβλημα των συνδαιτυμόνων φιλοσόφων Dining philosophers problem - 5 φιλόσοφοι - 5 ξυλάκια φαγητού P1 - Όταν ένας φιλόσοφος πεινάει, χρειάζεται 2 ξυλάκια για να φάει P5 P2 - Δεν μπορούν 2 φιλόσοφοι να χρησιμοποιούν το ίδιο ξυλάκι - Aποφυγή αδιεξόδου - Αποφυγή λιμοκτονίας P4 P3

Λύση στο πρόβλημα των συνδαιτυμόνων φιλοσόφων #define NEXT(x) ((x+1) % N) sema_t F[N]; //forks do { wait(f[i]); wait(f[next(i)]); eat(); signal(f[next(i)]); signal(f[i]); think(); } while (TRUE); P5 P1 P2 P4 P3

Λύση στο πρόβλημα των συνδαιτυμόνων φιλοσόφων #define NEXT(x) ((x+1) % N) sema_t F[N]; //forks do { wait(f[i]); wait(f[next(i)]); eat(); signal(f[next(i)]); signal(f[i]); think(); } while (TRUE); P5 P1 P2 1. P1 παίρνει F1 2. P2 παίρνει F2 3. P3 παίρνει F3 4. P4 παίρνει F4 5. P5 παίρνει F5 P4 P3

Λύση στο πρόβλημα των συνδαιτυμόνων φιλοσόφων #define NEXT(x) ((x+1) % N) sema_t F[N]; //forks do { wait(f[i]); wait(f[next(i)]); eat(); signal(f[next(i)]); signal(f[i]); think(); } while (TRUE); P5 L W L P1 W L W P2 1. P1 παίρνει F1 2. P2 παίρνει F2 3. P3 παίρνει F3 4. P4 παίρνει F4 5. P5 παίρνει F5 Αδιέξοδο! W P4 L W P3 L

Λύσεις στο πρόβλημα των συνδαιτυμόνων φιλοσόφων (σωστές) Λύσεις P1 P5 P2 P4 P3

Λύσεις στο πρόβλημα των συνδαιτυμόνων φιλοσόφων (σωστές) Λύσεις 1. Χρήση σημαφόρου, αρχικοποιημένου στην τιμή 4, ώστε σε κάθε περίπτωση να μην διεκδικούν και οι 5 φιλόσοφοι τα ξυλάκια. P5 P1 P2 P4 P3

Λύσεις στο πρόβλημα των συνδαιτυμόνων φιλοσόφων (σωστές) Λύσεις 1. Χρήση σημαφόρου, αρχικοποιημένου στην τιμή 4, ώστε σε κάθε περίπτωση να μην διεκδικούν και οι 5 φιλόσοφοι τα ξυλάκια. P5 P1 P2 2. Σε περίπτωση που ένας από τους φιλόσοφους ξεκινάει να πάρει ένα ξυλάκι με διαφορετική σειρά από ότι οι υπόλοιποι, τότε δεν μπορεί να δημιουργηθεί αδιέξοδο. P4 P3

Ελεγκτές/Παρακολουθητές (Monitors) Οι σημαφόροι παρέχουν βολικό και αποτελεσματικό μηχανισμό συγχρονισμού Ωστόσο: βάρος χρήσης στον προγραμματιστή (που δεν είναι ποτέ καλή ιδέα )

Ελεγκτές/Παρακολουθητές (Monitors) Οι σημαφόροι παρέχουν βολικό και αποτελεσματικό μηχανισμό συγχρονισμού Ωστόσο: βάρος χρήσης στον προγραμματιστή (που δεν είναι ποτέ καλή ιδέα ) Ελεγκτές/Παρακολουθητές: Υψηλού επιπέδου σχήματα συγχρονισμού που παρέχονται από τις γλώσσες προγραμματισμού Αφηρημένος τύπος δεδομένων (abstract data type -- ADT) Κρύβει λεπτομέρειες υλοποίησης Δεν επιτρέπει απευθείας πρόσβαση στα δεδομένα (ιδιωτικά δεδομένα) Ο προγραμματιστής ορίζει λειτουργίες (μεθόδους)

Ελεγκτές/Παρακολουθητές (παράδειγμα δομής) monitor MyMonitor { // shared variables int a; // methods procedure P_1(...) {... } procedure P_2(...) {... } } // initialization initialize() { a =...... }

Ελεγκτές/Παρακολουθητές Μηχανισμοί που παρέχονται Αμοιβαίος Αποκλεισμός (mutual exclusion) Μεταβλητές συνθήκης (condition variables)

Ελεγκτές/Παρακολουθητές Μηχανισμοί που παρέχονται Αμοιβαίος Αποκλεισμός (mutual exclusion) Όταν μια διεργασία εκτελεί μια λειτουργία, τότε η διεργασία βρίσκεται μέσα στον παρακολουθητή Είναι εγγυημένο ότι μόνο μια διεργασία μπορεί να είναι ενεργή μέσα στον παρακολουθητή Μεταβλητές συνθήκης (condition variables)

Ελεγκτές/Παρακολουθητές Μηχανισμοί που παρέχονται Αμοιβαίος Αποκλεισμός (mutual exclusion) Όταν μια διεργασία εκτελεί μια λειτουργία, τότε η διεργασία βρίσκεται μέσα στον παρακολουθητή Είναι εγγυημένο ότι μόνο μια διεργασία μπορεί να είναι ενεργή μέσα στον παρακολουθητή Μεταβλητές συνθήκης (condition variables) Μηχανισμός, ώστε μια διεργασία να αναστέλλει την λειτουργία της έως ότου ικανοποιηθεί μια συνθήκη (πχ Παραγωγός-Καταναλωτής) Λειτουργίες: wait(): Η διεργασία αδρανοποιείται μέχρι να κληθεί η signal(). signal(): Ενεργοποιεί (ακριβώς) μια αδρανοποιημένη διεργασία. (Πότε ;)

Παράδειγμα Παρακολουθητή Παραγωγός-Καταναλωτής #define NEXT(x) ((x + 1) % N) monitor ProducerConsumer { } // end ProducerConsumer

Παράδειγμα Παρακολουθητή Παραγωγός-Καταναλωτής #define NEXT(x) ((x + 1) % N) monitor ProducerConsumer { item_t buffer[n]; int in=0, out=0, count=0; condition full, empty; void enqueue(item_t item){ item_t dequeue(void){ } } // end ProducerConsumer }

Παράδειγμα Παρακολουθητή Παραγωγός-Καταναλωτής #define NEXT(x) ((x + 1) % N) monitor ProducerConsumer { item_t buffer[n]; int in=0, out=0, count=0; condition full, empty; void enqueue(item_t item){ while (count == N) wait(full); buffer[in] = item; in = NEXT(in); if (++count == 1) signal(empty); } } // end ProducerConsumer item_t dequeue(void){ }

Παράδειγμα Παρακολουθητή Παραγωγός-Καταναλωτής #define NEXT(x) ((x + 1) % N) monitor ProducerConsumer { item_t buffer[n]; int in=0, out=0, count=0; condition full, empty; void enqueue(item_t item){ while (count == N) wait(full); buffer[in] = item; in = NEXT(in); if (++count == 1) signal(empty); } } // end ProducerConsumer item_t dequeue(void){ item_t item; while (count == 0) wait(empty); item = buffer[out]; out = NEXT(out); if (count-- == N) signal(full); return item; }

Διεπαφή pthreads Υλοποιήσεις GNU libc, NPTL (2.6 linux) -- "1-1" Pth, νήματα χώρου χρήστη Διεπαφή Δημιουργία και έλεγχος νημάτων: pthread_{create,exit,join,cancel} Κλειδώματα (Mutexes): pthread_mutex_{init,destroy,lock,unlock,trylock} Μεταβλητές συνθήκης (condition variables): pthread_cond_{init,destroy,signal,broadcast,wait}

pthreads Hello World #include <stdio.h> #include <pthread.h> #define NUM_THREADS 8 #define pcreate pthread_create #define pjoin pthread_join void *hello(void *arg) { int *i = (int *)arg; printf("[%d] Hello!\n",*i); return NULL; } int main(int argc, char *argv[]) { pthread_t t[num_threads]; int i, ids[num_threads]; for (i=0; i<num_threads; i++){ ids[i] = i; pcreate(t+i,null,hello,ids+i); } for (i=0; i<num_threads; i++) pjoin(t[i], NULL); return 0; }

pthreads Hello World #include <stdio.h> #include <pthread.h> #define NUM_THREADS 8 #define pcreate pthread_create #define pjoin pthread_join void *hello(void *arg) { int *i = (int *)arg; printf("[%d] Hello!\n",*i); return NULL; } int main(int argc, char *argv[]) { pthread_t t[num_threads]; int i, ids[num_threads]; } for (i=0; i<num_threads; i++){ ids[i] = i; pcreate(t+i,null,hello,ids+i); } for (i=0; i<num_threads; i++) pjoin(t[i], NULL); return 0; $ gcc -Wall -O2 -lpthread -o hello hello.c $./hello [0] Hello! [2] Hello!...

pthreads: Mεταβλητές συνθήκης int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); Η συνάρτηση αναμονής έχει ως παράμετρο ένα lock (mutex) Μετά από ξύπνημα του νήματος θα πρέπει πάντα να ελέγχεται η συνθήκη (spurious wakeup)

Κεντρικό και πολλαπλά κλειδώματα για κοινούς πόρους Big lock vs fine-grain locking - Θεωρούμε: Διεργασίες ( x) Πόρους (Πx).Δ0.Δ2.Δ1.Π0.Π3.Π2..Π1

Κεντρικό και πολλαπλά κλειδώματα για κοινούς πόρους Big lock vs fine-grain locking - Θεωρούμε: Διεργασίες ( x) Πόρους (Πx) - Κεντρικό κλείδωμα (ΚΚ): Όποια διεργασία πάρει το ΚΚ μπορεί να χρησιμοποιήσει όλους τους πόρους.δ0.δ2.δ1.kk..π0..π1.π3.π2

Κεντρικό και πολλαπλά κλειδώματα για κοινούς πόρους Big lock vs fine-grain locking - Θεωρούμε: Διεργασίες ( x) Πόρους (Πx) - Κεντρικό κλείδωμα (ΚΚ): Όποια διεργασία πάρει το ΚΚ μπορεί να χρησιμοποιήσει όλους τους πόρους.δ0.δ2.δ1 - Πολλαπλά κλειδώματα (fine-grain locking) 1 κλείδωμα ανά διαθέσιμο πόρο + Δυνατότητα παραλληλίας..π0...π1..π3..π2

Κεντρικό και πολλαπλά κλειδώματα για κοινούς πόρους Big lock vs fine-grain locking - Θεωρούμε: Διεργασίες ( x) Πόρους (Πx) - Κεντρικό κλείδωμα (ΚΚ): Όποια διεργασία πάρει το ΚΚ μπορεί να χρησιμοποιήσει όλους τους πόρους.δ0.δ2.δ1 - Πολλαπλά κλειδώματα (fine-grain locking) 1 κλείδωμα ανά διαθέσιμο πόρο + Δυνατότητα παραλληλίας - Κίνδυνος αδιεξόδου (Δ0 έχει Π0 και περιμένει Π3, Δ2 έχει Π3 και περιμένει Π0)..Π0...Π1..Π3..Π2

Αναγκαίες συνθήκες για δημιουργία αδιεξόδου Αμοιβαίος αποκλεισμός Ένας τουλάχιστον πόρος να μην υποστηρίζει διαμοιραζόμενο τρόπο λειτουργίας Κράτημα και αναμονή Κατά την απόκτηση πρόσβασης στους πόρους που χρειάζεται οι διεργασίες θα πρέπει να μην απελευθερώνουν πόρους που έχουν δεσμεύσει και να περιμένουν να απελευθερωθούν οι υπόλοιποι Χωρίς Διακοπή Οι πόροι μπορούν να απελευθερωθούν μόνο εθελοντικά από τις διεργασίες που τους έχουν δεσμεύσει Κυκλική Αναμονή P 1 αναμένει πόρο της P 2... P n 1 αναμένει πόρο της P n P n αναμένει πόρο της P 1

Αποτροπή αδιεξόδων αφετηρία: αναγκαίες συνθήκες Αμοιβαίος αποκλεισμός Χρήση πόρων που μπορούν να διαμοιραστούν (πχ αρχεία για ανάγνωση) Κράτημα και αναμονή & Χωρίς Διακοπή Εναλλακτικά πρωτόκολλα Κυκλική Αναμονή Διάταξη πόρων και πραγματοποίηση αιτήσεων με συγκεκριμένη σειρά

Τέλος