This shows you the differences between two versions of the page.
|
java:semaphores [2017/03/18 21:44] gthanos |
java:semaphores [2017/03/18 21:44] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Σηματοφορείς ====== | ||
| - | |||
| - | Ο σηματοφορέας είναι μία οντότητα συγχρονισμού μεταξύ ανεξάρτητων ροών εργασίας. Ας υποθέσουμε ότι έχουμε ένα buffer Ν θέσεων μηνυμάτων μέσω του οποίου επικοινωνούν δύο διεργασίες. Αρχικά το buffer είναι άδειο, η διεργασία Α προσθέτει μηνύματα στο buffer και η διεργασία Β τα διαβάζει και τα αφαιρεί από το buffer. Η διαδικασία υπόκειται στους εξής περιορισμούς: | ||
| - | - Η διεργασία Β δεν μπορεί να διαβάσει από το buffer εάν το buffer είναι κενό. | ||
| - | - Η διεργασία Α δεν μπορεί να γράψει στο buffer εάν το buffer είναι γεμάτο. | ||
| - | |||
| - | Ας υποθέσουμε ότι ορίζουμε ένα σηματοφορέα ως εξής. Αρχικά ο σηματοφορέας έχει μία αρχική ακέραια τιμή μεγαλύτερη ή ίση με το μηδέν. Κάθε φορά που λαμβάνουμε ένα resource (θα εξηγηθεί) η τιμή του σηματοφορέα μειώνεται κατά 1, ενώ κάθε φορά που επιστρέφουμε ένα resource η τιμή αυξάνεται κατά 1. Εάν ο σηματοφορέας λάβει την τιμή μηδέν δεν μπορούμε να λάβουμε άλλο resource και η διεργασία που προσπαθεί να λάβει το resource μπλοκάρει. | ||
| - | |||
| - | Για το παραπάνω πρόβλημα ορίζουμε δύο σηματοφορείς (//write// και //read//) ως εξής: | ||
| - | - Ένας σηματοφορέας // | ||
| - | - Ένας σηματοφορεας //readSem// με αρχική 0. Κάθε φορά που γράφουμε 1 μήνυμα στο buffer ο σηματοφορέας αυξάνει την τιμή του κατά 1, ενώ κάθε φορά που διαβάζουμε 1 μήνυμα από το buffer ο σηματοφορέας μειώνει την τιμή του κατά 1. | ||
| - | |||
| - | Όταν το buffer είναι άδειος ο σηματοφορέας //readSem// έχει την τιμή 0 και η διαδικασία B μπλοκάρει μέχρι να γραφεί κάτι σε αυτό. Εάν το buffer είναι γεμάτο ο σηματοφορέας write έχει την τιμή 0 και η διαδικασία A μπλοκάρει μέχρι να διαβαστεί κάτι από το buffer. | ||
| - | |||
| - | Ο κώδικας για το γράψιμο και το διάβασμα στο buffer δίνεται σχηματικά ως εξής: | ||
| - | |||
| - | <code java> | ||
| - | // γράψιμο | ||
| - | writeSem.down() | ||
| - | buffer.write(msg); | ||
| - | readSem.up(); | ||
| - | | ||
| - | // διάβασμα | ||
| - | String msg; | ||
| - | readSem.down() | ||
| - | msg = buffer.read(); | ||
| - | writeSem.up(); | ||
| - | </ | ||
| - | |||
| - | Ο κώδικας για ένα σηματοφορέα γενικής χρήσης δίνεται παρακάτω: | ||
| - | |||
| - | <code java Semaphore.java> | ||
| - | public class Semaphore { | ||
| - | byte value = 1; | ||
| - | | ||
| - | public Semaphore(byte init_value) { | ||
| - | value = init_value; | ||
| - | } | ||
| - | | ||
| - | public synchronized void down() { | ||
| - | while(value==0) { | ||
| - | try { | ||
| - | wait(); | ||
| - | } catch(InterruptedException ex) {} | ||
| - | } | ||
| - | value--; | ||
| - | } | ||
| - | | ||
| - | public synchronized void up() { | ||
| - | value++; | ||
| - | notifyAll(); | ||
| - | } | ||
| - | } | ||
| - | </ | ||