User Tools

Site Tools


java:thread_signalling

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
java:thread_signalling [2017/03/19 21:32]
gthanos [Συγχρονισμός με χρήση wait(), notify(), notifyAll()]
java:thread_signalling [2018/03/09 11:43]
gthanos [Συγχρονισμός με χρήση wait(), notify(), notifyAll()]
Line 53: Line 53:
         System.out.println(Thread.currentThread().getName()+" awaites locked for the lock.");         System.out.println(Thread.currentThread().getName()+" awaites locked for the lock.");
       }       }
 +      // Uncomment the following line and see threads running concurrently.
 +      // Thread.sleep(10);
       lock.lock();          lock.lock();   
       for(int i=0; i<10; i++) {       for(int i=0; i<10; i++) {
Line 74: Line 76:
 Το παραπάνω σχήμα δεν είναι αποτελεσματικό ως προς τον συγχρονισμό και επίσης δαπανά πολλά 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()]]. Το παραπάνω σχήμα δεν είναι αποτελεσματικό ως προς τον συγχρονισμό και επίσης δαπανά πολλά 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()//. +Όταν ένα νήμα καλεί την μέθοδο //wait()// πάνω σε ένα αντικείμενο, τότε το νήμα κοιμάται έως ότου ένα άλλο νήμα καλέσει τη μέθοδο //notify()// πάνω στο ίδιο αντικείμενο. Τότε το νήμα που κοιμόταν ξυπνάει και συνεχίζει την εκτέλεση του. Το νήμα που καλεί τις //wait()// και //notify()// __θα πρέπει να έχει λάβει προηγουμένως το //monitor lock// για το συγκεκριμένο αντικείμενο__, δηλαδή τόσο η //wait()// όσο και η //notify()// __θα πρέπει να κληθούν μέσα σε μία συγχρονισμένη μέθοδο ή συγχρονισμένο μπλοκ__. Δείτε το παρακάτω παράδειγμα συγχρονισμού με χρήση των //wait()/notify()//.
- +
-<code java MonitorObject.java> +
-public class MonitorObject{ +
-+
-</code>+
  
 <code java MyWaitNotify.java> <code java MyWaitNotify.java>
 public class MyWaitNotify{ public class MyWaitNotify{
  
-  MonitorObject myMonitorObject = new MonitorObject(); +  Object myMonitorObject = new Object(); 
-  boolean wasSignalled = false;+  boolean wasSignalled = true;
  
   public void doWait(){   public void doWait(){
Line 109: Line 106:
  
 Η μέθοδος //notify()// ξυπνάει ένα νήμα που περιμένει στο συγκεκριμένο //monitor lock//. Όπως βλέπετε οι μέθοδοι //wait()// και //notify()// καλούνται μέσα σε ένα συγχρονισμένο block του οποίου το //monitor lock// αφορά το αντικείμενο από το οποίο καλούνται οι //wait()// και //notify()//. Το παραπάνω σχήμα είναι υποχρεωτικό, δηλαδή (ισχύουν και τα δύο παρακάτω): Η μέθοδος //notify()// ξυπνάει ένα νήμα που περιμένει στο συγκεκριμένο //monitor lock//. Όπως βλέπετε οι μέθοδοι //wait()// και //notify()// καλούνται μέσα σε ένα συγχρονισμένο block του οποίου το //monitor lock// αφορά το αντικείμενο από το οποίο καλούνται οι //wait()// και //notify()//. Το παραπάνω σχήμα είναι υποχρεωτικό, δηλαδή (ισχύουν και τα δύο παρακάτω):
-  οι //wait()// και //notify()// θα πρέπει να κληθούν μέσα σε ένα συγχρονισμένο block ή μία συγχρονισμένη μέθοδο.  +  οι //wait()// και //notify()// θα πρέπει να κληθούν μέσα σε ένα συγχρονισμένο block ή μία συγχρονισμένη μέθοδο.  
-  Κατά την κλήση των //wait()/notify()// μπορούμε να καλέσουμε τις wait()/notify() μόνο το αντικείμενο του οποίου έχουμε αποκτήσει το //monitor lock//. Εάν δεν ισχύει αυτό τότε λαμβάνουμε ένα [[http://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html|IllegalMonitorStateException]]. +  Κατά την κλήση των //wait()/notify()// μπορούμε να καλέσουμε τις wait()/notify() μόνο για το αντικείμενο του οποίου έχουμε αποκτήσει το //monitor lock// 
- +  * Εάν δεν ισχύουν τα δύο παραπάνω δεν έχουμε καμία εγγύηση για το σωστό συγχρονισμό των νημάτων.
-<code java> +
-  public void doWait(){ +
-    synchronized(myMonitorObject){ +
-      if(!wasSignalled){ +
-        try{ +
-          myMonitorObject2.wait(); +
-         } catch(InterruptedException e){...} +
-      } +
-      //clear signal and continue running. +
-      wasSignalled = false; +
-    } +
-  } +
-</code>+
  
 Εκτός από τη μέθοδο //notify()// που ξυπνάει ένα νήμα από όσα περιμένουν υπάρχει και η //notifyAll()// που ξυπνάει όλα τα νήματα που περιμένουν για το συγκεκριμένο //monitor lock//. Όταν περισσότερα του ενός νήματα περιμένουν, το ποιο νήμα από όλα θα ξυπνήσει η μέθοδος //notify()// δεν ελέγχεται από εσάς. Είστε όμως βέβαιοι ότι θα ξυπνήσει ένα νήμα. Εκτός από τη μέθοδο //notify()// που ξυπνάει ένα νήμα από όσα περιμένουν υπάρχει και η //notifyAll()// που ξυπνάει όλα τα νήματα που περιμένουν για το συγκεκριμένο //monitor lock//. Όταν περισσότερα του ενός νήματα περιμένουν, το ποιο νήμα από όλα θα ξυπνήσει η μέθοδος //notify()// δεν ελέγχεται από εσάς. Είστε όμως βέβαιοι ότι θα ξυπνήσει ένα νήμα.
  
 <WRAP important 80% round center> <WRAP important 80% round center>
-Ο παραπάνω κώδικας δεν μπορεί να εξασφαλίσει τον συγχρονισμό αν αντικαταστήσουμε την notify() με την notifyAll(). Γιατί;+Ο παραπάνω κώδικας δεν μπορεί να εξασφαλίσει τον συγχρονισμό αν αντικαταστήσουμε την //notify()// με την //notifyAll()//. Γιατί;
 </WRAP> </WRAP>
  
-Ας δούμε τώρα πως υλοποιείται ο παραπάνω μηχανισμός συγχρονισμού. Όταν ένα νήμα περιμένει μέσω της wait() ελευθερώνει παράλληλα το //monitor lock// που έχει λάβει για το αντικείμενο //myMonitorObject//, Η απελευθέρωση του //monitor lock// επιτρέπει σε άλλα νήματα που δεν έχουν το lock να το λάβουν μπαίνοντας σε ένα συγχρονισμένο block ή συγχρονισμένη μέθοδο. +Ας δούμε τώρα πως υλοποιείται ο παραπάνω μηχανισμός συγχρονισμού. Όταν ένα νήμα περιμένει μέσω της //wait()// ελευθερώνει παράλληλα το //monitor lock// που έχει λάβει για το αντικείμενο //myMonitorObject//, Η απελευθέρωση του //monitor lock// επιτρέπει σε άλλα νήματα που δεν έχουν το //lock// να το λάβουν μπαίνοντας σε ένα συγχρονισμένο block ή συγχρονισμένη μέθοδο. 
  
 <WRAP tip 80% round center> <WRAP tip 80% round center>
Line 147: Line 131:
 public class MyWaitNotify2{ public class MyWaitNotify2{
  
-  MonitorObject myMonitorObject = new MonitorObject();+  Object myMonitorObject = new Object();
   boolean wasSignalled = false;   boolean wasSignalled = false;
  
Line 181: Line 165:
 public class SimpleLock { public class SimpleLock {
  
-  MonitorObject myMonitorObject = new MonitorObject();+  Object myMonitorObject = new Object();
   boolean wasSignalled = false;   boolean wasSignalled = false;
  
Line 204: Line 188:
 } }
 </code> </code>
 +
 +|Προηγούμενο: [[:java:synchronized_methods_blocks| Συγχρονισμένες μέθοδοι και blocks ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[java:deadlock | Αδιέξοδο στην χρήση των πόρων ]]|
  
java/thread_signalling.txt · Last modified: 2018/03/09 12:02 by gthanos