java:thread_signalling

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

java:thread_signalling [2015/03/29 20:16]
gthanos [Συγχρονισμός με χρήση wait(), notify(), notifyAll()]
java:thread_signalling [2016/02/26 11:15]
Line 1: Line 1:
-====== Συγχρονισμός Νημάτων ====== 
- 
-Ο συγχρονισμός νημάτων έχει σαν στόχο να επιτρέπει σε διαφορετικά νήματα να διαβάζουν ή να γράφουν με ασφάλεια σε διαμοιραζόμενες μεταβλητές χωρίς να προκύπτουν ασάφειες ως προς τις τιμές των μεταβλητών αυτών λόγω ταυτόχρονης μεταβολής τους. Ας υποθέσουμε ότι έχουμε δύο νήματα Α, Β και το νήμα Α θέλει να ειδοποιήσει το νήμα Β μόλις ολοκληρώσει την επεξεργασία των δεδομένων του, ώστε εκείνο να ξεκινήσει την επεξεργασία των δεδομένων. 
- 
-===== Συγχρονισμός μέσω διαμοιραζόμενων αντικειμένων ===== 
- 
-Ο πιο απλός τρόπος για να επικοινωνήσουν δύο νήματα μεταξύ τους είναι μέσω διαμοιραζόμενων αντικειμένων. Για το παραπάνω παράδειγμα,​ ας υποθέσουμε ότι το νήμα Α θέτει την boolean τιμή //​hasDataToProcess//​ σε true μέσα από μία συγχρονισμένη μέθοδο και το νήμα Β διαβάζει την τιμή //​hasDataToProcess//​ και πάλι μέσω μίας συγχρονισμένης μεθόδου 
- 
-<code java MySignal.java>​ 
-public class MySignal{ 
- 
-  protected boolean hasDataToProcess = false; 
- 
-  public synchronized boolean hasDataToProcess(){ 
-    return this.hasDataToProcess;​ 
-  } 
- 
-  public synchronized void setHasDataToProcess(boolean hasData){ 
-    this.hasDataToProcess = hasData;  ​ 
-  } 
- 
-} 
-</​code>​ 
- 
-===== Συγχρονισμός μέσω διαρκούς επανάληψης ===== 
- 
-Το νήμα Β περιμένει έως ότου τα δεδομένα να είναι διαθέσιμα περιμένοντας διαρκώς σε ένα while() βρόγχο (loop), όπως παρακάτω 
- 
-<code java> 
-protected MySignal sharedSignal = ... 
- 
-... 
- 
-while(!sharedSignal.hasDataToProcess()){ 
-  //do nothing... busy waiting 
-} 
-</​code>​ 
-Στο παράδειγμα αυτό το νήμα περιμένει,​ αλλά παράλληλα παραμένει και ενεργό (busy). ​ 
- 
-===== Συγχρονισμός με χρήση wait(), notify(), notifyAll() ===== 
- 
-Το παραπάνω σχήμα αν και είναι αποτελεσματικό ως προς τον συγχρονισμό δαπανά πολλά resources καθώς το νήμα Β παραμένει ενεργό περιμένοντας. Θα ήταν πιο αποδοτικό αν αντί να παραμένει ενεργό το νήμα Β //"​κοιμόταν"//​ περιμένοντας το νήμα Α να ολοκληρώσει. Η Java διαθέτει ένα μηχανισμό προκειμένου να επιτρέψει σε νήματα να κοιμηθούν περιμένοντας τα νήματα που εκτελούνται να ολοκληρώσουν το έργο τους. Συγκεκριμένα διαθέτει τρεις μεθόδους που επιτρέπουν το συγκεκριμένο συγχρονισμό [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Object.html#​wait--|wait()]],​ [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Object.html#​notify--|notify()]],​ [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Object.html#​notifyAll--|notifyAll()]]. 
- 
-Όταν ένα νήμα καλεί την μέθοδο //wait()// πάνω σε ένα αντικείμενο,​ τότε το νήμα κοιμάται έως ότου ένα άλλο νήμα καλέσει τη μέθοδο //​notify()//​ πάνω στο ίδιο αντικείμενο. Τότε το νήμα που κοιμόταν ξυπνάει και συνεχίζει την εκτέλεση του. Προκειμένου να κληθούν οι //wait()// και //​notify()//​ __το νήμα που τις καλεί θα πρέπει να λάβει το monitor lock για το συγκεκριμένο αντικείμενο__,​ δηλαδή τόσο η //wait()// όσο και η //​notify()//​ θα πρέπει να κληθούν μέσα σε μία συγχρονισμένη μέθοδο ή συγχρονισμένο μπλοκ. Δείτε το παρακάτω παράδειγμα συγχρονισμού με χρήση των //​wait()/​notify()//​. 
- 
-<code java MonitorObject.java>​ 
-public class MonitorObject{ 
-} 
-</​code>​ 
- 
-<code java MyWaitNotify.java>​ 
-public class MyWaitNotify{ 
- 
-  MonitorObject myMonitorObject = new MonitorObject();​ 
- 
-  public void doWait(){ 
-    synchronized(myMonitorObject){ 
-      try{ 
-        myMonitorObject.wait();​ 
-      } catch(InterruptedException e){...} 
-    } 
-  } 
- 
-  public void doNotify(){ 
-    synchronized(myMonitorObject){ 
-      myMonitorObject.notify();​ 
-    } 
-  } 
-} 
-</​code>​ 
- 
-Η μέθοδος //​notify()//​ ξυπνάει ένα νήμα που περιμένει στο συγκεκριμένο //monitor lock//. Όπως βλέπετε οι μέθοδοι wait() και notify() καλούνται μέσα σε ένα συγχρονισμένο block του οποίου το monitor lock αφορά το αντικείμενο με το οποίο καλούνται οι //​wait()/​notify()//​. Το παραπάνω σχήμα είναι υποχρεωτικό,​ δηλαδή δεν μπορούμε να αποκτήσουμε το monitor lock ενός διαφορετικού αντικειμένου από αυτό με το οποίο καλούμε τις wait()/​notify(). ​ 
- 
-Εκτός της //​notify()//​ υπάρχει και η //​notifyAll()//​ που ξυπνάει όλα τα νήματα που περιμένουν στο συγκεκριμένο //monitor lock//​. ​ 
- 
- 
  
java/thread_signalling.txt · Last modified: 2016/02/26 11:15 (external edit)