Κλειδώματα

Είναι πιθανό πολλές εργασίες στο σύστημα να χρειαστεί να αποκτήσουν πρόσβαση και να χειριστούν το ίδιο αντικείμενο. Η κλάση ILock καθορίζει ένα πρωτόκολλο για την αποκλειστική εκχώρηση δικαιωμάτων πρόσβασης σε ένα κοινόχρηστο αντικείμενο. Όταν η εργασία χρειάζεται να αποκτήσει πρόσβαση σε κάποιο κοινόχρηστο αντικείμενο. δεσμεύει ένα κλείδωμα για αυτό το αντικείμενο. Όταν ολοκληρώσει το χειρισμό του αντικειμένου, απελευθερώνει το κλείδωμα.

Ένα κλείδωμα δημιουργείται συνήθως όταν το κοινόχρηστο αντικείμενο δημιουργείται από μια πρόσθετη λειτουργία ή η πρόσβαση σε αυτό επιτυγχάνεται από την ίδια πρόσθετη λειτουργία. Δηλαδή, ένας κώδικας με παραπομπή στο κοινόχρηστο αντικείμενο έχει επίσης παραπομπή και στο κλείδωμά του. θα ξεκινήσουμε δημιουργώντας ένα κλείδωμα, myLock, το οποίο θα χρησιμοποιηθεί για τον έλεγχο της πρόσβασης στο myObject:

   ...
   myObject = initializeImportantObject();
   IJobManager jobMan = Platform.getJobManager();
   myLock = jobMan.newLock();
   ...

Μια ισχυρή υλοποίηση του ILock παρέχεται από την πλατφόρμα. Η λειτουργία διαχείρισης εργασίας παρέχει χρήσεις αυτού του κλειδώματος για χρήση του από τους πελάτες. Αυτά τα κλειδώματα "γνωρίζονται μεταξύ τους" και μπορούν να αποφύγουν τα κυκλικά αδιέξοδα. (θα εξηγήσουμε περισσότερο τη σημασία της πρότασης αυτή παρακάτω.)

Όταν ο κώδικας μιας εργασίας απαιτεί πρόσβαση στο myObject, πρέπει πρώτα να δεσμεύει το κλείδωμα αυτού του αντικειμένου. Το ακόλουθο τμήμα κώδικα παρουσιάζει ένα κοινό ιδίωμα για εργασία με ένα κλείδωμα:

...
// I need to manipulate myObject, so I get its lock first.
try {
	myLock.acquire();
	updateState(myObject);  // manipulate the object
   } finally {
	lock.release();
}
...

Η μέθοδος acquire() δεν θα επιστρέψει αποτέλεσμα μέχρι να εκχωρηθεί στην εργασία κλήσης αποκλειστική πρόσβαση στο κλείδωμα. Με άλλα λόγια, εάν κάποια άλλη εργασία έχει ήδη δεσμεύσει το κλείδωμα, τότε αυτός ο κώδικας θα μπλοκάρει μέχρι να γίνει διαθέσιμο το κλείδωμα. Σημειώστε ότι ο κώδικας που δεσμεύει το κλείδωμα και χειρίζεται το myObject είναι αναδιπλωμένος σε μια ενότητα try, έτσι ώστε το κλείδωμα να μπορεί να απελευθερωθεί εάν προκύψουν τυχόν εξαιρέσεις κατά την εργασία με το αντικείμενο.

Φαίνεται αρκετά εύκολο, έτσι δεν είναι; Ευτυχώς, η χρήση των κλειδωμάτων είναι αρκετά ξεκάθαρη. Επίσης είναι επανεισαγόμενα, δηλαδή δεν χρειάζεται να ανησυχείτε για ενδεχόμενη δέσμευση του ίδιου κλειδώματος από την εργασία σας πολλές φορές. Κάθε κλείδωμα διατηρεί μια μέτρηση του αριθμού δεσμεύσεων και απελευθερώσεων για ένα συγκεκριμένο νήμα, και θα απελευθερωθεί από μια εργασία μόνον όταν ο αριθμός των απελευθερώσεων θα είναι ίσος με τον αριθμό των δεσμεύσεων.

Αδιέξοδο

Νωρίτερα σημειώσαμε ότι τα κλειδώματα που παρέχονται από τη λειτουργία διαχείρισης εργασίας γνωρίζουν τα μεν την ύπαρξη των δε και μπορούν να αποφύγουν τα κυκλικά αδιέξοδα. Για να κατανοήσουμε πώς εμφανίζεται ένα αδιέξοδο, ας δούμε ένα απλό σενάριο. Ας υποθέσουμε ότι η "Εργασία Α" δεσμεύει το "Κλείδωμα Α" και τελικά επιχειρεί να δεσμεύσει το "Κλείδωμα Β". Εν τω μεταξύ, το "Κλείδωμα Β" περιέχεται στην "Εργασία Β" η οποία είναι αυτή τη στιγμή μπλοκαρισμένη περιμένοντας στο "Κλείδωμα Α". Αυτό το είδος αδιεξόδου υποδηλώνει ένα υποκείμενο πρόβλημα σχεδίασης με τη χρήση των κλειδωμάτων μεταξύ των εργασιών. Ενώ αυτή η απλή περίπτωση μπορεί να αποφευχθεί αρκετά εύκολα, οι πιθανότητες τυχαίας εισαγωγής αδιεξόδου αυξάνονται καθώς αυξάνεται ο αριθμός των εργασιών και των κλειδωμάτων που χρησιμοποιούνται στην σχεδίασή σας.

Ευτυχώς, η πλατφόρμα θα σας βοηθήσει να αναγνωρίσετε τα αδιέξοδα. Όταν η λειτουργία διαχείρισης εντοπίσει μια συνθήκη αδιεξόδου, εκτυπώνει διαγνωστικές πληροφορίες στο αρχείο που περιγράφει τη συνθήκη του αδιεξόδου. Στη συνέχεια διαχωρίζει το αδιέξοδο εκχωρώντας προσωρινά δικαιώματα πρόσβασης στα κλειδώματα που ανήκουν σε μια μπλοκαρισμένη εργασία σε άλλες εργασίες που περιμένουν σε αυτά. Είναι σημαντικό να δοκιμάζετε προσεκτικά κάθε υλοποίηση που προϋποθέτει πολλαπλά κλειδώματα και να διορθώνετε τυχόν συνθήκες αδιεξόδου που αναφέρονται από την πλατφόρμα.