Αρχική ΑΕΠΠ - Δομές Δεδομένων Λειτουργικά Συστήματα Δίκτυα Υπολογιστών ΙΙ Βάσεις Δεδομένων Παιδαγωγικά - Διδακτική

Εισαγωγικά

Εισαγωγή στα Λ.Σ. Βασικές Δομές Η/Υ Βασικές Δομές Λ.Σ

Διεργασίες

Διεργασίες Χρονοπρογραμματισμός Συγχρονισμός

Αδιέξοδα

Μνήμη

Μονοπρογραμματισμός Εναλλαγή Εικονική Μνήμη Κατάτμηση

Είσοδος / Έξοδος

Σύστημα Αρχείων

Διεπαφή Υλοποίηση

 Ιστορικό Πρόσφατες αλλαγές Εκτύπωση Αναζήτηση

Ιστορικό: OS.ClassicalProblems

Απόκρυψη μικρών αλλαγών - Αλλαγές περιεχομένου

04-09-2008 (20:25) από Άρης -
Πρόσθεση σειρών 47-90:
!! Προτεραιότητα στου Αναγνώστες - Αποφυγή Λιμοκτονίας Εγγραφέων

Η λύση είναι όμοια με εκείνη που δίνει προτεραιότητα στους αναγνώστες. Προσθέτουμε ένα σημαφόρο (writerQueue) στον οποίο θα αναστέλλονται οι εγγραφείς. Αν υπάρχουν εγγραφείς σ' αυτήν την ουρά, τότε οι αναγνώστες που φτάνουν θα πρέπει να ανασταλούν, έτσι θα ολοκληρώσουν όσοι είναι στη βάση και θα αφήσουν την κρίσιμη περιοχή ελεύθερη σε έναν εγγραφέα. Οι δύο διεργασίες δίνονται παρακάτω.

(:source lang=cpp linenum:) [@
typedef int semaphore;

int rc = 0;
semaphore mutex, writersQueue, db;
mutex = writersQueue = db = 1;

void reader(void) {
down(&writersQueue); /* Αν υπάρχει writer που περιμένει η reader αναστέλλεται */
up(&writersQueue); /* Κάνει ξανά την writersQueue 1 */

down(&mutex); /* Αποκλειστική πρόσβαση στην rc */
rc++; /* Ένας ακόμη reader */
if (rc==1) down(&db); /* Ο πρώτος προσπαθεί να πάρει αποκλειστική πρόσβαση */
up(&mutex); /* Ελεύθερη πρόσβαση στην rc */

read_data_base(); /* κρίσιμο τμήμα */

down(&mutex); /* Αποκλειστική πρόσβαση στην rc */
rc--; /* Ένας reader λιγότερος */
if (rc==0) up(&db); /* Αν είναι ο τελευταίος ελευθερώνει την ουρά στον db */
up(&mutex); /* Ελεύθερη πρόσβαση στην rc */

use_data_read(); /* μη κρίσιμο τμήμα */
}

void writer(void) {
down(&writersQueue); /* Ένας writer στην ουρά. Αν υπάρχουν άλλοι αναστέλλεται */
down(&db); /* Αποκλειστική πρόσβαση */

write_data_base(); /* Κρίσιμο τμήμα */

up(&writersQueue); /* Απελευθέρωσε έναν writer ή reader από την ουρά */
up(&db); /* Ελεύθερη πρόσβαση */
}
@]

Αν ξεκινήσει ένας writer, ο σημαφόρος writerQueue γίνεται 0 στην γραμμή 27. Αν έρθει writer θα ανασταλεί στην 27, ενώ αν έρθει reader θα ανασταλεί στην γραμμή 8. Ο writer θα μπει στο κρίσιμο τμήμα του και θα ελευθερώσει την ουρά στον writerQueue. Ο χρονοδρομολογητής μπορεί να επιλέξει μια διεργασία reader ή writer.
Αν ξεκινήσει ένας reader, δεν θα ανασταλεί στην γραμμή 8. Ας υποθέσουμε ότι έχει μπει και στο κρίσιμο τμήμα του. Αν έρθει ένας ακόμη reader μπορεί να μπει στο κρίσιμο τμήμα του. Αν έρθει ένας writer θα μειώσει τον writerQueue και θα ανασταλεί στη γραμή 29. Τώρα, αν έρθει reader θα ανασταλεί στην 8 και αν έρθει writer θα ανασταλεί στην 27. Έτσι, όταν ολοκληρώσουν οι reader που είναι στα κρίσιμα τμήματά τους, τότε ο writer που είχε ανασταλεί στην 29 θα μπει στο κρίσιμο τμήμα του.
Αλλαγή σειρών 93-115 από:
(:source lang=cpp:) [@
int readcount, writecount = 0;
semaphore rsem, wsem = 1; //
semaphore x,y,z = 1; //

void reader(){
while(1){
wait(z);
wait(rsem);
wait(x);
readcount++;
if (readcount==1)
wait(wsem);
signal(x);
signal(rsem);
signal(z);
doReading();
wait(x);
readcount--;
if (readcount==0)
signal(wsem);
signal(x);
}
σε:
Θα χρησιμοποιήσουμε δύο μεταβλητές rc και wc που μετράνε αντίστοιχα τους αναγνώστες και τους εγγραφείς που είναι στα κρίσιμα τμήματά τους. Οι σημαφόροι rc_mutex και wc_mutex χρησιμοποιούνται για την αποκλειστική πρόσβαση στις μεταβλητές rc και wc αντίστοιχα.
Ο σημαφόρος readersQueue χρησιμοποιείται ώστε να δημιουργηθεί μία ουρά αναγνωστών, όταν οι εγγραφείς προσπαθούν να μπουν στο κρίσιμο τμήμα τους. Όταν readersQueue είναι 1 δεν υπάρχει διεργασία στην ουρά. Διαφορετικά οι διεργασίες αναστέλλονται και δημιουργούν ουρά. Ο σημαφόρος db ελέγχει την πρόσβαση στο κρίσιμο τμήμα της κάθε διεργασίας.


(:source lang=cpp linenum:) [@
typedef int semaphore;

int rc, wc;
rc = wc = 0;

semaphore rc_mutex, wc_mutex, readersQueue, db
rc_mutex = wc_mutex = readersQueue = db = 1;

void reader(void) {
down(&readersQueue);

down(&rc_mutex);
rc++;
if (rc==1) down(&db);
up(&rc_mutex);

up(&readersQueue);

read_db(); /* κρίσιμο τμήμα */

down(&rc_mutex);
rc--;
if (rc==0) up(&db);
up(&rc_mutex);
Αλλαγή σειρών 124-139 από:
void writer(){
while(1){
wait(y);
writecount++;
if (writecount==1)
wait(rsem);
signal(y);
wait(wsem);
doWriting();
signal(wsem);
wait(y);
writecount--;
if (writecount==0)
signal(rsem);
signal(y);
}
σε:
void writer(void) {
down(&wc_mutex);
wc++;
if (wc==1) down(&readersQueue);
up(&wc_mutex);

down(&db);
write_db();
up(&db);

down(&wc_mutex);
wc--;
if (wc==0) up(&readersQueue);
up(&wc_mutex);
Αλλαγή σειρών 139-145 από:
@]
σε:
@]

Αν ένας αναγνώστης φτάσει στο κρίσιμο τμήμα του έχει κάνει down τον db (γραμμή 11) αλλά όχι τον readersQueue (γραμμή 17). Έτσι, αν φτάσει ένας αναγνώστης μπορεί να κάνει down τον readersQueue. Αυτό θα κάνει όσους αναγνώστες φτάνουν να αναστέλλονται στη γραμμή 10. Όταν ο τελευταίος αναγνώστης βγει από το κρίσιμο τμήμα του θα κάνει up τον db (γραμμή 23) το οποίο ελευθερώνει τους εγγραφείς που έχουν ανασταλεί.

Αν ένας εγγραφέας είναι στο κρίσιμο τμήμα του, έχει κάνει down τόσο τον readersQueue, όσο και τον db. Αυτό έχει το αποτέλεσμα ότι ούτε άλλος εγγραφέας ούτε αναγνώστης μπορεί να μπει στο κρίσιμο τμήμα του. Επίσης, όσοι εγγραφείς φτάνουν αυξάνουν την μεταβλητή wc και περιμένουν στον readersQueue. Αυτό σημαίνει ότι όσο φτάνουν εγγραφείς, ένας ένας θα μπαίνουν στο κρίσιμο τμήμα τους και οι αναγνώστες θα περιμένουν. Μόνο ο τελευταίος εγγραφέας θα κάνει up τον readersQueue και θα μπορούν να προχωρήσουν οι αναγνώστες.

Εδώ μπορεί να παρατηρηθεί το αντίστοιχο φαινόμενο με την προτεραιότητα στους αναγνώστες, δηλαδή, ότι οι αναγνώστες μπορεί να λιμοκτονούν ή τουλάχιστον να υφίστανται μεγάλες καθυστερήσεις.
26-08-2008 (19:09) από Άρης -
Αλλαγή σειράς 15 από:
(:sourceblock lang=cpp:) [@
σε:
(:source lang=cpp:) [@
26-08-2008 (19:03) από Άρης -
Αλλαγή σειρών 17-19 από:
semaphore rc = 1; // Ελέγχει την πρόσβαση στα δεδομένα
semaphore db = 1; // Ελέγχει την πρόσβαση στην μεταβλητή readcount
σε:
semaphore wsem = 1; //
semaphore x = 1; //
Αλλαγή σειρών 21-22 από:
while(true){
wait(rc); // Αποκλειστική πρόσβαση στην μεταβλητή readcount
σε:
while(1){
wait(x);
Αλλαγή σειρών 25-26 από:
down(db); // Προσπάθεια να πάρει αποκλειστική πρόσβαση στα δεδομένα
signal(rc);
σε:
wait(wsem);
signal(x);
Αλλαγή σειράς 28 από:
wait(rc);
σε:
wait(x);
Αλλαγή σειρών 31-32 από:
up(db);
signal(rc);
σε:
signal(wsem);
signal(x);
Αλλαγή σειρών 37-38 από:
while(true){
down(db);
σε:
while(1){
wait(wsem);
Αλλαγή σειράς 40 από:
up(db);
σε:
signal(wsem);
Αλλαγή σειράς 51 από:
semaphore rc = 1, wc = 1; //
σε:
semaphore rsem, wsem = 1; //
Αλλαγή σειράς 57 από:
wait(rc);
σε:
wait(rsem);
Αλλαγή σειράς 61 από:
wait(wc);
σε:
wait(wsem);
Αλλαγή σειράς 63 από:
signal(rc);
σε:
signal(rsem);
Αλλαγή σειράς 69 από:
signal(wc);
σε:
signal(wsem);
Αλλαγή σειράς 79 από:
wait(rc);
σε:
wait(rsem);
Αλλαγή σειράς 81 από:
wait(wc);
σε:
wait(wsem);
Αλλαγή σειράς 83 από:
signal(wc);
σε:
signal(wsem);
Αλλαγή σειράς 87 από:
signal(rc);
σε:
signal(rsem);
Αλλαγή σειρών 90-91 από:
}
σε:
}
@]
26-08-2008 (18:57) από Άρης -
Πρόσθεση σειρών 1-90:
! Αναγνώστες - Εγγραφείς

The R-W problem is another classic problem for which design of synchronization and concurrency mechanisms can be tested.

* There is a data area that is shared among a number of processes.
* Any number of readers may simultaneously write to the data area.
* Only one writer at a time may write to the data area.
* If a writer is writing to the data area, no reader may read it.
* If there is at least one reader reading the data area, no writer may write to it.
* Readers only read and writers only write
* A process that reads and writes to a data area must be considered a writer (consider producer or consumer)

!! Semaphore Solution: Readers have Priority

(:sourceblock lang=cpp:) [@
int readcount = 0;
semaphore rc = 1; // Ελέγχει την πρόσβαση στα δεδομένα
semaphore db = 1; // Ελέγχει την πρόσβαση στην μεταβλητή readcount

void reader(){
while(true){
wait(rc); // Αποκλειστική πρόσβαση στην μεταβλητή readcount
readcount++;
if (readcount==1)
down(db); // Προσπάθεια να πάρει αποκλειστική πρόσβαση στα δεδομένα
signal(rc);
doReading();
wait(rc);
readcount--;
if (readcount==0)
up(db);
signal(rc);
}
}

void writer(){
while(true){
down(db);
doWriting();
up(db);
}
}
@]

Once readers have gained control, a flow of reader processes could starve the writer processes.

!! Semaphore Solution: Writers have Priority

(:source lang=cpp:) [@
int readcount, writecount = 0;
semaphore rc = 1, wc = 1; //
semaphore x,y,z = 1; //

void reader(){
while(1){
wait(z);
wait(rc);
wait(x);
readcount++;
if (readcount==1)
wait(wc);
signal(x);
signal(rc);
signal(z);
doReading();
wait(x);
readcount--;
if (readcount==0)
signal(wc);
signal(x);
}
}

void writer(){
while(1){
wait(y);
writecount++;
if (writecount==1)
wait(rc);
signal(y);
wait(wc);
doWriting();
signal(wc);
wait(y);
writecount--;
if (writecount==0)
signal(rc);
signal(y);
}
}

Τελευταία ενημέρωση: 04-09-2008 (20:25)

Copyright 2008 - Άρης Φεργάδης