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
java:thread_signalling [2015/04/19 15:22]
gthanos [Συγχρονισμός με χρήση wait(), notify(), notifyAll()]
java:thread_signalling [2016/02/26 11:15] (current)
Line 135: Line 135:
 ===== Ξαφνικά ξυπνήματα (Spurious wake-ups) ===== ===== Ξαφνικά ξυπνήματα (Spurious wake-ups) =====
  
-Υπάρχει η πιθανότητα ένα νήμα να ξυπνήσε ακόμη και δίχως να κληθεί η //​notify()//​ ή η //​notifyAll()//​. Σε αυτή την περίπτωση αν το νήμα λάβει το lock θα ξυπνήσει και θα συνεχίσει την εκτέλεση του δίχως να εξετάσει αν έχει έρθει ένα σήμα ή όχι. Για το λόγο αυτό, καλό θα είναι ο έλεγχος που γίνεται παραπάνω (μέσα στην //if()//) να αντικατασταθεί με ένα while() loop ώστε να είμαστε σίγουροι ότι όσο δεν έχει έρθει κάποιο σήμα το νήμα που περιμένει δεν θα συνεχίσει την εκτέλεση του. Δείτε τον τελικό κώδικα παρακάτω+Υπάρχει η πιθανότητα ένα νήμα να ξυπνήσει ακόμη και δίχως να κληθεί η //​notify()//​ ή η //​notifyAll()//​. Αν και οι περιπτώσεις αυτές δεν είναι συχνές δεν θα πρέπει να αποκλειστούν. Σε αυτή την περίπτωση αν το νήμα λάβει το **lock** θα ξυπνήσει και θα συνεχίσει την εκτέλεση του δίχως να εξετάσει αν έχει έρθει ένα σήμα ή όχι. Για το λόγο αυτό, καλό θα είναι ο έλεγχος που γίνεται παραπάνω (μέσα στην //if()//) να αντικατασταθεί με ένα while() loop ώστε να είμαστε σίγουροι ότι όσο δεν έχει έρθει κάποιο σήμα το νήμα που περιμένει δεν θα συνεχίσει την εκτέλεση του. Δείτε τον τελικό κώδικα παρακάτω
  
 <code java MyWaitNotify2.java>​ <code java MyWaitNotify2.java>​
Line 164: Line 164:
 </​code>​ </​code>​
  
-<​WRAP ​tip>+<​WRAP ​info 80% center round>
 Το παραπάνω σχήμα δουλεύει επίσης πολύ καλά εάν πολλαπλά νήματα περιμένουν σε ένα monitor lock.  Το παραπάνω σχήμα δουλεύει επίσης πολύ καλά εάν πολλαπλά νήματα περιμένουν σε ένα monitor lock. 
 Αν τα νήματα αυτά ξυπνούν μέσα από μία κλήση της μεθόδου //​notifyAll()//,​ τότε μέσα από τον παραπάνω κώδικα μόνο ένα από τα νήματα θα λάβει το monitor lock (το πρώτο που ξύπνησε και έλαβε το lock του αντικειμένου myMonitorObject). Τα υπόλοιπα,​ όταν με την σειρά τους θα λάβουν το lock, θα ελέγξουν την τιμή της μεταβλητής //​wasSignalled//​ και θα πάνε πάλι για ύπνο εφόσον την βρουν ίση με //false//. Αν τα νήματα αυτά ξυπνούν μέσα από μία κλήση της μεθόδου //​notifyAll()//,​ τότε μέσα από τον παραπάνω κώδικα μόνο ένα από τα νήματα θα λάβει το monitor lock (το πρώτο που ξύπνησε και έλαβε το lock του αντικειμένου myMonitorObject). Τα υπόλοιπα,​ όταν με την σειρά τους θα λάβουν το lock, θα ελέγξουν την τιμή της μεταβλητής //​wasSignalled//​ και θα πάνε πάλι για ύπνο εφόσον την βρουν ίση με //false//.
 </​WRAP>​ </​WRAP>​
  
 +Παρατηρήστε ότι η κλάση **MyWaitNotify2** υλοποιεί ένα μία απλή κλειδαριά,​ όπου μόνο ένα νήμα μπορεί να πάρει την κλειδαριά,​ ενώ όλα τα υπόλοιπα νήματα περιμένουν. Μόλις ολοκληρώσει την επεξεργασία ελευθερώνει την κλειδαριά και ενημερώνει ένα από τα νήματα που περιμένουν να ξεκινήσει. Η παραπάνω κλάση θα μπορούσε να γραφεί και ως εξής:
  
 +<code java SimpleLock.java>​
 +public class SimpleLock {
 +
 +  MonitorObject myMonitorObject = new MonitorObject();​
 +  boolean wasSignalled = false;
 +
 +  public void lock(){
 +    synchronized(myMonitorObject){
 +      while(!wasSignalled){
 +        try{
 +          myMonitorObject.wait();​
 +         } catch(InterruptedException e){...}
 +      }
 +      //clear signal and continue running.
 +      wasSignalled = false;
 +    }
 +  }
 +
 +  public void unlock(){
 +    synchronized(myMonitorObject){
 +      wasSignalled = true;
 +      myMonitorObject.notify();​
 +    }
 +  }
 +}
 +</​code>​
  
java/thread_signalling.1429456932.txt.gz · Last modified: 2016/02/26 11:15 (external edit)