This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
java:thread_signalling [2015/04/18 18:03] gthanos [Συγχρονισμός με χρήση wait(), notify(), notifyAll()] |
java:thread_signalling [2015/04/19 15:17] gthanos [Συγχρονισμός Νημάτων] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Συγχρονισμός Νημάτων ====== | ====== Συγχρονισμός Νημάτων ====== | ||
- | Ο συγχρονισμός νημάτων έχει σαν στόχο να επιτρέπει σε διαφορετικά νήματα να διαβάζουν ή να γράφουν με ασφάλεια σε διαμοιραζόμενες μεταβλητές χωρίς να προκύπτουν ασάφειες ως προς τις τιμές των μεταβλητών αυτών λόγω ταυτόχρονης μεταβολής τους. Ας υποθέσουμε ότι έχουμε δύο νήματα Α, Β και το νήμα Α θέλει να ειδοποιήσει το νήμα Β μόλις ολοκληρώσει την επεξεργασία των δεδομένων του, ώστε εκείνο να ξεκινήσει την επεξεργασία των δεδομένων. | + | Ο συγχρονισμός νημάτων έχει σαν στόχο να επιτρέπει σε διαφορετικά νήματα να διαβάζουν ή να γράφουν με ασφάλεια σε διαμοιραζόμενες μεταβλητές χωρίς να προκύπτουν ασάφειες ως προς τις τιμές των μεταβλητών αυτών λόγω ταυτόχρονης μεταβολής τους. Ο προσεκτικός αναγνώστης θα παρατηρήσει ότι το παραπάνω μπορούμε να το επιτύχουμε και με την χρήση συγχρονισμένων μπλοκ ή συγχρονισμένων μεθόδων. Το παραπάνω είναι εν μέρη σωστό, μόνο αν τα νήματα δύναται να εκτελούνται παράλληλα. Εάν τα νήματα δεν μπορούν να εκτελεστούν παράλληλα, αλλά το ένα νήμα θα πρέπει να περιμένει το άλλο να ολοκληρώσει τότε τα συγχρονισμένα block από μόνα τους δεν αποτελούν λύση. Σε αυτή την περίπτωση απαιτείται η έννοια της κλειδαριάς (lock). |
+ | |||
+ | Ας υποθέσουμε ότι έχουμε δύο νήματα Α, Β και το νήμα Α θέλει να ειδοποιήσει το νήμα Β μόλις ολοκληρώσει την επεξεργασία των δεδομένων του, ώστε εκείνο να ξεκινήσει την επεξεργασία των δεδομένων που δημιουργήθηκαν. Δεν μας αρκεί δηλαδή τα νήματα Α, Β να εκτελούνται παράλληλα, αλλά θα θέλαμε το Β να ξεκινήσει την επεξεργασία μόλις το Α ολοκληρώσει. | ||
===== Συγχρονισμός μέσω διαμοιραζόμενων αντικειμένων και διαρκούς επανάληψης ===== | ===== Συγχρονισμός μέσω διαμοιραζόμενων αντικειμένων και διαρκούς επανάληψης ===== | ||
Line 61: | Line 63: | ||
} | } | ||
</code> | </code> | ||
- | Στο παράδειγμα αυτό το νήμα περιμένει, αλλά παράλληλα παραμένει και ενεργό (busy). Επίσης, θα παρατηρήσετε ότι αν τα δύο νήματα δεν καλέσουν την μέθοδο sleep() στην αρχή, τότε με μεγάλη πιθανότητα τα δύο νήματα θα εκκινήσουν ταυτόχρονα και ταυτόχρονα διαβάσουν την τιμή **signal.hasDataToProcess() -> -1** και θα αρχίσουν να τρέχουν παράλληλα πράγμα που δεν το θέλουμε. | + | Στο παράδειγμα αυτό το νήμα περιμένει, αλλά παράλληλα παραμένει και ενεργό (busy). Επίσης, θα παρατηρήσετε ότι με σημαντική πιθανότητα (αλλά όχι σίγουρα) τα δύο νήματα θα εκκινήσουν ταυτόχρονα και ταυτόχρονα διαβάσουν την τιμή **signal.hasDataToProcess() -> -1** και θα αρχίσουν να εκτελούνται παράλληλα πράγμα που δεν το θέλουμε. |
===== Συγχρονισμός με χρήση wait(), notify(), notifyAll() ===== | ===== Συγχρονισμός με χρήση wait(), notify(), notifyAll() ===== | ||
Line 101: | Line 103: | ||
</code> | </code> | ||
- | Η μέθοδος //notify()// ξυπνάει ένα νήμα που περιμένει στο συγκεκριμένο //monitor lock//. Όπως βλέπετε οι μέθοδοι //wait()// και //notify()// καλούνται μέσα σε ένα συγχρονισμένο block του οποίου το //monitor lock// αφορά το αντικείμενο από το οποίο καλούνται οι //wait()// και //notify()//. Το παραπάνω σχήμα είναι υποχρεωτικό, δηλαδή | + | Η μέθοδος //notify()// ξυπνάει ένα νήμα που περιμένει στο συγκεκριμένο //monitor lock//. Όπως βλέπετε οι μέθοδοι //wait()// και //notify()// καλούνται μέσα σε ένα συγχρονισμένο block του οποίου το //monitor lock// αφορά το αντικείμενο από το οποίο καλούνται οι //wait()// και //notify()//. Το παραπάνω σχήμα είναι υποχρεωτικό, δηλαδή (ισχύουν και τα δύο παρακάτω): |
- οι //wait()// και //notify()// θα πρέπει να κληθούν μέσα σε ένα συγχρονισμένο block ή μία συγχρονισμένη μέθοδο. Αν δεν γίνει αυτό τότε λαμβάνουμε ένα [[http://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html|IllegalMonitorStateException]]. | - οι //wait()// και //notify()// θα πρέπει να κληθούν μέσα σε ένα συγχρονισμένο block ή μία συγχρονισμένη μέθοδο. Αν δεν γίνει αυτό τότε λαμβάνουμε ένα [[http://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html|IllegalMonitorStateException]]. | ||
- Κατά την κλήση των //wait()/notify()// δεν μπορούμε να αποκτήσουμε το monitor lock ενός διαφορετικού αντικειμένου από αυτό με το οποίο καλούμε τις wait()/notify(), δηλ δεν μπορούμε να κάνουμε κάτι σαν το παρακάτω | - Κατά την κλήση των //wait()/notify()// δεν μπορούμε να αποκτήσουμε το monitor lock ενός διαφορετικού αντικειμένου από αυτό με το οποίο καλούμε τις wait()/notify(), δηλ δεν μπορούμε να κάνουμε κάτι σαν το παρακάτω |