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

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

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

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

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

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

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

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

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

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

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

Νήµατα. Πολύ σηµαντικό

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

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

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

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

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

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

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

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

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

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

Προγραμματισμός συστημάτων UNIX/POSIX

lab13grades Άσκηση 2 -Σωστά απελευθερώνετε ολόκληρη τη λίστα και την κεφαλή

Δομημένος Προγραμματισμός

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

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

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

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

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

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

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

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

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

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

Προγραμματισμός συστημάτων UNIX/POSIX. Σήματα (signals)

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

Sheet2. Σωστή, και µπράβο που µεριµνήσατε για λίστες διαφορετικών µεγεθών.

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

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

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

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

- Το πρόγραµµα σας δίνει τα αναµενόµενα αποτελέσµατα.

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

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

Στοίβες με Δυναμική Δέσμευση Μνήμης

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

Προγραμματισμός Η/Υ 1 (Εργαστήριο)

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

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

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

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

Προγραμματισμός Η/Υ (ΤΛ2007 )

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δίκτυα Επικοινωνιών ΙΙ: Network Programming UDP Sockets, Signals

26/3/2012 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι) Β. Δημακόπουλος

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

Κεφάλαιο , 3.2: Συναρτήσεις II. (Διάλεξη 12)

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

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

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Θέτοντας και επιστρέφοντας την τιµή της προτεραιότητας διεργασίας

Δομές Δεδομένων. Καθηγήτρια Μαρία Σατρατζέμη. Τμήμα Εφαρμοσμένης Πληροφορικής. Δομές Δεδομένων. Τμήμα Εφαρμοσμένης Πληροφορικής

υναµικές οµές εδοµένων (συν.) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα:

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

ΕΡΓΑΣΤΗΡΙΟ 5 ΣΗΜΕΙΩΣΕΙΣ

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

υναµική έσµευση Μνήµης (συν.) ΕΠΛ 132 Αρχές Προγραµµατισµού ΙΙ 2 Εφαρµογή

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

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

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Βαθμός Σχόλια. lab5 PASS PASS PASS PASS PASS. Οριακά PASS - Καλή δουλειά

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

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

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

Μεθόδων Επίλυσης Προβλημάτων

Φροντιστήριο 4 Σκελετοί Λύσεων

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

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

ΕΡΓΑΣΤΗΡΙΟ 9: Συμβολοσειρές και Ορίσματα Γραμμής Εντολής

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

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

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

Εργαστήριο 5. Εαρινό Εξάμηνο

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ II. Υφαντόπουλος Νικόλαος Υποψήφιος Διδάκτορας Contact:

FAIL PASS PASS οριακά

Ενδεικτική περιγραφή μαθήματος

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

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

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #2

Εισαγωγή στον δομημένο προγραμματισμό

οµές (structures) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: Πίνακες δοµών, δείκτες σε δοµές, και αυτοαναφορικές δοµές.

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

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

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

2η Προγραµµατιστική Εργασία

ιαφάνειες παρουσίασης #5 (β)

Εργαστήριο 2: Πίνακες

(Κεφάλαιο 2.7 και 12) Αρχεία στην C. (Διάλεξη 15)

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

Transcript:

Εργαστήριο 12 Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t) Να γράψετε πρόγραμμα που να δημιουργεί 1 νήμα. Έτσι στο πρόγραμμα σας θα υπάρχουν 2 νήματα (το ένα νήμα είναι το αρχικό νήμα που εκτελεί τη main). Το ένα νήμα (αρχικό) θα παίζει το ρόλο του «παραγωγού» το οποίο θα δημιουργεί και θα βάζει 10 κόμβους (nodes) σε μια στοίβα (υλοποιημένη σαν συνδεδεμένη λίστα). Στον κάθε κόμβο θα αποθηκεύεται ένας αριθμός από το 1 έως το 10. Το άλλο νήμα σαν «καταναλωτής» θα αφαιρεί τους κόμβους από την στοίβα και θα εμφανίζει τα περιεχόμενά τους στην οθόνη. Στην υλοποίηση αυτή, ο μοιραζόμενος (από τα νήματα) πόρος είναι η λίστα. Σημειώσεις: Κάθε κόμβος θα αποτελείται από μια δομή όπως φαίνεται πιο κάτω: struct node { int n_number; struct node *n_next Κάθε νήμα θα πρέπει να κλειδώνει με χρήση δυαδικών σηματοφόρων ή με άλλα λόγια μεταβλητών αμοιβαίου αποκλεισμού (mutual exclusion) τα κοινόχρηστα δεδομένα προτού αποκτήσει πρόσβαση πάνω τους. Κάθε φορά που το αρχικό νήμα θα τοποθετεί στη στοίβα ένα κόμβο, θα πρέπει να σηματοδοτεί μια συνθήκη (pthread_cond_t) στην οποία το άλλο νήμα περιμένει. Περισσότερες πληροφορίες για τις μεταβλητές συνθήκης δείτε πιο κάτω. Οι μεταβλητές συνθήκης (condition variables), παρέχουν ένα άλλο τρόπο συγχρονισμού νημάτων. Σε αντίθεση με τις μεταβλητές αμοιβαίου αποκλεισμού, οι οποίες χρησιμοποιούνται για το συγχρονισμό των νημάτων ελέγχοντας την πρόσβαση στα προστατευμένα δεδομένα, οι μεταβλητές συνθήκης επιτρέπουν στα νήματα να συγχρονισθούν με βάση τη τιμή των δεδομένων αυτών. Χωρίς την ύπαρξη των μεταβλητών συνθήκης, ο προγραμματιστής θα έπρεπε να ορίζει τα νήματα να ελέγχουν συνέχει τη τιμή μιας κοινής μεταβλητής για μια συγκεκριμένη τιμή ώστε να ελέγξουν αν έχει ικανοποιηθεί μια συγκεκριμένη συνθήκη. Ο τρόπος αυτός είναι γνωστός ως απασχολημένη αναμονή (busy wait) και καταναλώνει πολύ περισσότερους πόρους συστήματος από ότι είναι αναγκαίο αφού όλα τα νήματα είναι απασχολημένα κάνοντας συνεχείς ελέγχους. Οι μεταβλητές συνθήκης επιτρέπουν να επιτευχθεί ο σκοπός αυτός χωρίς τα νήματα να τίθενται σε συνεχή αναμονή. Η μεταβλητή συνθήκης χρησιμοποιείται πάντα σε συνεργασία με μια μεταβλητή αμοιβαίου αποκλεισμού. Για τη δημιουργία και την καταστροφή μιας μεταβλητής συνθήκης χρησιμοποιούνται οι παρακάτω συναρτήσεις: int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); Αφού μια μεταβλητή συνθήκης δηλωθεί ως pthread_cond_t, πρέπει να αρχικοποιηθεί με την pthread_cond_init πριν την χρήση της. Μετά τη χρήση της μεταβλητής συνθήκης, οι πόροι που έχουν δεσμευθεί μπορούν να ελευθερωθούν με τη συνάρτηση pthread_cond_destroy.

Για την αναμονή μέχρι την ικανοποίηση μια συνθήκης και για τη σηματοδότησή της χρησιμοποιούνται οι πιο κάτω συναρτήσεις: 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) Ένα νήμα-καταναλωτής που θέλει να αποκτήσει πρόσβαση στον μοιραζόμενο πόρο για τον «καταναλώσει» πρέπει να ελέγξει την τιμή του πόρου ή αν υπάρχει πόρος για να καταναλώσει. Για παράδειγμα, στην άσκησή μας, ο καταναλωτής πρέπει να ελέγξει αν υπάρχει κόμβος στην λίστα. Αν όχι πρέπει να μπει σε αναμονή. Η συνάρτηση pthread_cond_wait θέτει το νήμα (έστω Α καταναλωτής) που την καλεί σε αναμονή μέχρι τη σηματοδότησή της μεταβλητής συνθήκης cond. Η συνάρτηση αυτή πρέπει να κληθεί αφού η μεταβλητή αμοιβαίου αποκλεισμού mutex έχει κλειδωθεί (pthread_mutex_lock). Όταν καλεστεί η συνάρτηση pthread_cond_wait, η μεταβλητή mutex ξεκλειδώνεται αυτόματα και το νήμα Α που την κάλεσε μπλοκάρει. Έτσι μπορεί άλλο νήμα (έστω Β παραγωγός) να κλειδώσει τη mutex (pthread_mutex_lock) για να έχει πρόσβαση στον κοινό πόρο. Όταν το νήμα Β ικανοποιήσει τη συνθήκη την οποία αναμένει το μπλοκαρισμένο νήμα Α (π.χ. βάλει κόμβο μέσα στη λίστα) τότε το νήμα Β πρέπει να καλέσει τη συνάρτηση pthread_cond_signal ή pthread_cond_broadcast. Για να κληθεί οποιαδήποτε από τις 2 αυτές συναρτήσεις πρέπει η μεταβλητή mutex (στο νήμα Β) να είναι κλειδωμένη. Η συνάρτηση pthread_cond_signal στέλνει ένα σήμα στο μπλοκαρισμένο νήμα Α για να μπορέσει να ξεμπλοκάρει. Για να ξεμπλοκάρει το νήμα Α πρέπει πρώτα το νήμα Β μετά την κλήση της pthread_cond_signal να ξεκλειδώσει τη mutex (pthread_mutex_unlock). Όταν γίνει αυτό, τότε η mutex ξανακλειδώνεται αυτόματα στο νήμα Α και μπορεί να συνεχίσει για να έχει πρόσβαση στον κοινό πόρο. Όταν τελειώσει το νήμα Α τότε πρέπει να ξεκλειδώσει τη μεταβλητή mutex (pthread_mutex_unlock) με τη σειρά του. Η κλήση της συνάρτησης pthread_cond_signal ξεμπλοκάρει τουλάχιστον ένα από τα νήματα που είναι μπλοκαρισμένα στη μεταβλητή συνθήκης cond (αν υπάρχουν νήματα μπλοκαρισμένα στη μεταβλητή cond). Η κλήση της συνάρτησης pthread_cond_broadcast ξεμπλοκάρει όλα τα νήματα που είναι στη τρέχουσα φάση μπλοκαρισμένα στη μεταβλητή συνθήκης cond. Δείτε παράδειγμα πιο κάτω. #include <stdlib.h> #include <stdio.h> #include <string.h> #include <signal.h> #include <pthread.h> // compile with gcc mutexcond.c -o mutexcond -Wall -lpthread pthread_cond_t cond; pthread_mutex_t mutex; // shared variable int x = 0;

void *thread(void *v) { printf("\n"); printf("\n"); pthread_mutex_lock(&mutex); if (x == 0) pthread_cond_wait(&cond, &mutex); printf("i've been unlocked and d the shared variable x=%d.\n", x); // shared variable has been d x -= 10; pthread_mutex_unlock(&mutex); return NULL; int main() { char cmd[10]; pthread_t t; // initializes the mutex // upon successful initialization, // the state of the mutex becomes initialized and unlocked pthread_mutex_init(&mutex, NULL); // initializes the condition variable // upon successful initialization, // the state of the condition variable becomes initialized pthread_cond_init(&cond, NULL); printf("type to a value in the shared variable.\n"); printf("type to generate a r to the value of the shared variable.\n"); printf("type quit to/ exit program.\n"); while(fscanf(stdin, "%s", cmd)!= EOF) { if(strcmp(cmd, "") == 0) { printf("\n"); // lock mutex to a value in the shared variable pthread_mutex_lock(&mutex); x += 10; // unblock one thread blocked on the condition variable pthread_cond_signal(&cond); // unlock mutex pthread_mutex_unlock(&mutex); else if(strcmp(cmd, "") == 0) { // create a thread to shared variable value pthread_create(&t, NULL, thread, NULL); else if(strcmp(cmd, "quit") == 0) { break; pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0;

Παράδειγμα Εκτέλεσης (με κόκκινο η είσοδος του χρήστη). Με κίτρινο highlight το νήμαπαραγωγός (πατέρας) και με πράσινο highlight το νήμα-καταναλωτής. Type to a value in the shared variable. Type to generate a r to the value of the shared variable. Type quit to/ exit program. I've been unlocked and d the shared variable x=30. I've been unlocked and d the shared variable x=20. I've been unlocked and d the shared variable x=10. I've been unlocked and d the shared variable x=10. I've been unlocked and d the shared variable x=10. quit

Μέθοδοι διαχείρισης νημάτων σε πολυνηματικές εφαρμογές Στα πλαίσια του εργαστηρίου αυτού θα θεωρήσουμε ότι η πολυνηματική εφαρμογή που μας ενδιαφέρει είναι ένας εξυπηρετητής (server). Ο εξυπηρετητής θα πρέπει να είναι σε θέση να εξυπηρετεί «ταυτόχρονα» πολλές αιτήσεις από πελάτες. Δεν πρέπει, δηλαδή, να τελειώσει πρώτα με την εξυπηρέτηση μιας αίτησης και μετά να δέχεται νέες. Για να το πετύχουμε αυτό, θα πρέπει να εκμεταλλευτούμε τη δυνατότητα ύπαρξης πολλών νημάτων μέσα στη διεργασία του εξυπηρετητή. Στο κείμενο που ακολουθεί περιγράφονται δύο διαφορετικοί τρόποι με τους οποίους μπορούμε να προσεγγίσουμε τη διαχείριση των νημάτων: 1. Τεχνική Α: Δημιουργία ενός καινούργιου νήματος για την επεξεργασία μιας αίτησης, ενώ το αρχικό νήμα περιμένει νέες αιτήσεις 2. Τεχνική B: Δημιουργία ενός thread-pool για τη διαχείριση των νέων αιτήσεων. Για την περίπτωση αυτή θα δούμε δυο διαφορετικές ιδέες υλοποίησης. Στα πλαίσια της εργαστηριακής άσκησης 4 για τη δημιουργία ενός εξυπηρετητή (server) όλες οι προσεγγίσεις είναι αποδεκτές (δεν είναι δηλαδή απαραίτητο να χρησιμοποιηθεί thread-pool) όσον αφορά τη λειτουργία του προγράμματος. Όμως η μη χρησιμοποίηση thread-pool ενδέχεται να σας στοιχίσει βαθμούς στο κομμάτι της επίδοσης και της αρχιτεκτονικής σχεδίασης του συστήματος. Τεχνική Α: Δημιουργία ενός καινούργιου νήματος για την επεξεργασία μιας αίτησης, ενώ το αρχικό νήμα περιμένει νέες αιτήσεις Η προσέγγιση αυτή αποτελεί τον απλούστερο τρόπο πολυνηματικής εφαρμογής. Υπάρχει το αρχικό νήμα το οποίο περιμένει αιτήσεις από πελάτες (εκτός από το νήμα αυτό μπορεί να υπάρχουν και άλλα νήματα τα οποία διαχειρίζονται άλλου είδους εργασίες πέραν της εξυπηρέτησης πελατών, όπως π.χ., της διαχείρισης γραμμής εντολών). Για κάθε εισερχόμενη αίτηση το αρχικό νήμα δημιουργεί ένα καινούργιο νήμα το οποίο εξυπηρετεί τον αιτητή, και με το πέρας της αποστολής του το νήμα αυτό τερματίζει τη λειτουργία του. Η προσέγγιση αυτή δεν είναι πολύ καλή για τους ακόλουθους λόγους: 1. Η δημιουργία και καταστροφή νημάτων δεν είναι ιδιαίτερα ελεγχόμενη, γεγονός που μπορεί να αποβεί εξαιρετικά προβληματικό σε κάποιες περιπτώσεις. 2. Η δημιουργία ενός καινούργιου νήματος είναι ακριβή (παρόλο που είναι πιο φθηνή από τη δημιουργία μιας νέας διεργασίας). Στην συνεχεία πρέπει να αποδεσμεύσουμε τα δεδομένα που σχετίζονται με τον νήμα και τέλος να το απελευθερώσουμε, γεγονός που επιφέρει μεγαλύτερο κόστος 3. Ανά πάσα στιγμή δεν μπορούμε να ξέρουμε τον μέγιστο αριθμό νημάτων, επομένως μπορεί η διεργασία του εξυπηρετητή να ξεπεράσει το επιτρεπτό όριο μνήμης με αποτέλεσμα να χάσουμε την υπηρεσία. Τεχνική Β: Δημιουργία ενός thread-pool για τη διαχείριση των νέων αιτήσεων Η δεύτερη προσέγγιση αφορά τη δημιουργία ενός thread-pool από το αρχικό νήμα. Με τον όρο thread-pool, αναφερόμαστε στην δημιουργία ενός σταθερού αριθμού νημάτων-εργατών (ο αριθμός επιλέγεται ανάλογα με την εφαρμογή). Τα νήματα που βρίσκονται στο thread-pool συναγωνίζονται για την εξυπηρέτηση κάθε καινούργιας αίτησης. Δηλαδή κάθε καινούργια αίτηση ανατίθεται σε κάποιο από τα νήματα που δεν έχει δουλειά και περιμένει. Τα νήματα του thread-pool, αφού εξυπηρετήσουν ένα πελάτη, δεν τερματίζουν, αλλά μεταβαίνουν σε

κατάσταση αναμονής για να εξυπηρετήσουν άλλο πελάτη. Αν δεν υπάρχει διαθέσιμο νήμα, το αρχικό θα πρέπει να περιμένει μέχρι να υπάρξει, χωρίς να δέχεται νέες αιτήσεις. Πιο συγκεκριμένα εάν υπάρξουν περισσότερες αιτήσεις από το μέγιστο αριθμό νημάτων στο pool τότε το σύστημα απορρίπτει την αίτηση κλείνοντας το socket (χωρίς να επιστρέφει οποιανδήποτε απάντηση στον πελάτη). Για τη διαχείριση των νημάτων του pool και την εξυπηρέτηση των αιτήσεων μπορούμε να χρησιμοποιήσουμε την πιο κάτω λογική: 1. Τα νήματα εργάτες δημιουργούνται από την αρχή στον εξυπηρετητή από το αρχικό νήμα και τα thread IDs τους αποθηκεύονται σε ένα πίνακα. 2. Δημιουργούμε μια ουρά από εργασίες όπου ο κάθε κόμβος είναι μια νέα εισερχόμενη αίτηση σύνδεσης. Το αρχικό νήμα (παραγωγός) δέχεται αιτήσεις από τους πελάτες και για κάθε νέα σύνδεση εισάγει ένα νέο κόμβο στην ουρά αν υπάρχει διαθέσιμο νήμα (καταναλωτής) για να την εξυπηρετήσει. Αλλιώς (αν δεν υπάρχει διαθέσιμο νήμα καταναλωτής) η αίτηση για σύνδεση απορρίπτεται και το αρχικό νήμα κλείνει το socket που άνοιξε με την accept για εξυπηρέτηση του πελάτη. Η ουρά αυτή είναι ο κοινός (μοιραζόμενος) πόρος. 3. Η πρόσβαση στην ουρά (κοινός πόρος) για εισαγωγή κόμβου (από νήμα-παραγωγός) ή εξαγωγή κόμβου για εξυπηρέτηση (από νήματα-καταναλωτές) πρέπει να ελέγχεται μέσω σηματοφόρου και μεταβλητής συνθήκης. Όταν η ουρά δεν έχει εργασίες για να τύχουν επεξεργασίας, τα νήματα καταναλωτές είναι αδρανή (κολλημένα σε μεταβλητή συνθήκης).