Syncχρονισμός σε Java
Τι είναι Syncχρονισμός σε Java?
In Java, ο συγχρονισμός αναφέρεται στη δυνατότητα ελέγχου της πρόσβασης πολλαπλών νημάτων σε οποιονδήποτε κοινόχρηστο πόρο. Είναι μια ιδανική επιλογή όπου θέλουμε να επιτρέψουμε μόνο σε ένα νήμα να έχει πρόσβαση στον κοινόχρηστο πόρο.
Αυτή η προσέγγιση εκτέλεσης αναφέρεται συνήθως ως «ασύγχρονος» προγραμματισμός. Υπάρχουν επίσης νήματα σε αυτούς τους επεξεργαστές, οι οποίοι είναι ελαφριές διεργασίες που μπορούν να εκτελούν εντολές ταυτόχρονα.
Τύποι Syncχρονισμός
Υπάρχουν δύο τύποι μεθόδων συγχρονισμού Java:
1) Συγχρονισμός διαδικασίας
2) Συγχρονισμός νημάτων.
Ας μελετήσουμε το Thread και Συγχρονισμός διαδικασίας λεπτομερώς.
Συγχρονισμός διαδικασίας: Διαχειρίζεται το συγχρονισμό μεταξύ προγραμμάτων. Για παράδειγμα, προγράμματα όπως το `Microsoft Word" και "Acrobat reader" εκτελούνται ως μεμονωμένες διαδικασίες.
Συγχρονισμός νημάτων: Η ταυτόχρονη εκτέλεση του κρίσιμου πόρου από δύο ή περισσότερα Threads ονομάζεται Thread Syncχρονισμός. Μπορείτε να ομαδοποιηθείτε περαιτέρω σε αλληλοαποκλειόμενη επικοινωνία και επικοινωνία μεταξύ νημάτων.
Τι είναι το Lock in Java?
Κλειδώσει Java είναι χτισμένο γύρω από μια εσωτερική οντότητα γνωστή ως οθόνη ή κλειδαριά. Όλο το αντικείμενο έχει μια κλειδαριά που σχετίζεται με αυτά. Έτσι, το νήμα που χρειάζεται συνεπή πρόσβαση στα πεδία ενός αντικειμένου πρέπει να αποκτήσει το κλείδωμα του αντικειμένου πριν αποκτήσει πρόσβαση σε αυτά και απελευθερώνει το κλείδωμα όταν ολοκληρωθεί η εργασία. Αυτό διασφαλίζει ότι μόνο ένα νήμα έχει πρόσβαση στα κοινόχρηστα δεδομένα κάθε φορά.
Πρόγραμμα πολλαπλών νημάτων με συγχρονισμό
Ένα πρόγραμμα πολλαπλών νημάτων είναι μια μέθοδος ή μπλοκ που προστατεύεται από παρεμβολές από άλλα νήματα που μοιράζονται τον ίδιο πόρο που υποδεικνύεται χρησιμοποιώντας τη λέξη-κλειδί «συγχρονισμένο».
Χρησιμοποιώντας τη συγχρονισμένη μέθοδο
Οποιαδήποτε μέθοδος δηλώνεται ως συγχρονισμένη είναι γνωστή ως συγχρονισμένη μέθοδος. Χρησιμοποιείται επίσης για το κλείδωμα ενός αντικειμένου για οποιονδήποτε κοινόχρηστο πόρο. Έτσι, όταν ένα νήμα επικαλείται μια συγχρονισμένη μέθοδο. Παίρνει αυτόματα στην κατοχή του την κλειδαριά για αυτό το αντικείμενο και την απελευθερώνει όταν ολοκληρώσει την εργασία του.
Σημείωση: Η συγχρονισμένη λέξη-κλειδί δεν μπορεί να λειτουργήσει με κλάσεις και μεταβλητές. Μόνο μέθοδοι και μπλοκ μπορούν να χρησιμοποιηθούν με τη λέξη-κλειδί.
Γιατί να χρησιμοποιήσετε το Syncσυγχρονισμένη μέθοδος;
- Χρησιμοποιείται για το κλείδωμα ενός αντικειμένου για τυχόν κοινόχρηστους πόρους.
- Το αντικείμενο λαμβάνει το κλείδωμα κάθε φορά που καλείται η συγχρονισμένη μέθοδος.
- Η κλειδαριά δεν απελευθερώνεται έως ότου το νήμα ολοκληρώσει τη λειτουργία του
Σύνταξη:
Acess_modifiers synchronized return_type method_name (Method_Parameters) { }
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Επεξήγηση Κώδικα:
Εκτελέστε αυτό το παράδειγμα και παρατηρήστε ότι το νήμα «0» παίρνει πρώτα το κλείδωμα του αντικειμένου «mathService» και χρησιμοποιεί αυτό το κλείδωμα αποκλειστικά μέχρι να ολοκληρωθεί η εκτέλεσή του. Τα νήματα "0" και "1" δεν παρεμβάλλονται σε αυτόν τον κώδικα. Η έξοδος είναι όπως φαίνεται παρακάτω.
Παραγωγή:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Χρήση συγχρονισμένου μπλοκ
Ας υποθέσουμε ότι δεν θέλετε να συγχρονίσετε ολόκληρη τη μέθοδο. Αντίθετα, θέλετε να συγχρονίσετε μερικές γραμμές κώδικα. Εκείνη την εποχή, το SyncΤο συγχρονισμένο μπλοκ βοήθησε στον συγχρονισμό του επιλεγμένου Java κώδικας. SyncΟι κλειδαριές συγχρονισμένης μεθόδου έχουν πρόσβαση στη μέθοδο, ενώ οι κλειδαριές συγχρονισμένων μπλοκ προσπελάζονται στο αντικείμενο.
class MathService { void getSumOfArray(int[] numbers) { synchronized (this){ int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Επεξήγηση κώδικα:
Με την εκτέλεση αυτού του κωδικού, θα παρατηρήσετε ότι λειτουργεί χωρίς παρεμβολές. Στη συγχρονισμένη μέθοδο, το κλείδωμα εφαρμόζεται με τη μέθοδο, αλλά στο συγχρονισμένο μπλοκ, το κλείδωμα εφαρμόζεται από το αντικείμενο. Βεβαιωθείτε ότι η έξοδος είναι όπως φαίνεται παρακάτω.
Παραγωγή:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Επεξήγηση κωδικού:
Όταν εκτελείτε αυτόν τον κωδικό, θα σημειώσετε ότι λειτουργεί χωρίς παρεμβολές, κάτι που περιμέναμε. Στη συγχρονισμένη μέθοδο, το κλείδωμα εφαρμόζεται με τη μέθοδο, αλλά στη μέθοδο συγχρονισμένου μπλοκ, το κλείδωμα εφαρμόζεται από το αντικείμενο.
Χρήση στατικού συγχρονισμού
In Java συγχρονισμός, εάν υπάρχουν περισσότερα από ένα αντικείμενα, δύο νήματα μπορεί να αποκτήσουν τις κλειδαριές και να εισέλθουν σε ένα συγχρονισμένο μπλοκ ή μπλοκ, με ξεχωριστό κλείδωμα για κάθε αντικείμενο. Για να αποφευχθεί αυτό, μπορεί να χρησιμοποιηθεί στατικός συγχρονισμός. Syncθα χρησιμοποιηθούν συγχρονισμένες λέξεις-κλειδιά πριν από τις στατικές μεθόδους.
Σημείωση: Στον στατικό συγχρονισμό, η πρόσβαση κλειδώματος είναι στην κλάση, όχι στο αντικείμενο και τη μέθοδο.
Κώδικας για την επίδειξη του προβλήματος του κλειδώματος πολλαπλών αντικειμένων
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Επεξήγηση κωδικού:
Όταν δημιουργούμε μια άλλη παρουσία του 'MathService', εισάγουμε παρεμβολές στα νήματα καθώς θα παρεμβάλλονται με τα δύο αντικείμενα. Σημειώστε ότι το νήμα «0» και το νήμα «2» παρεμβάλλονται με τα δύο αντικείμενα, ενώ το νήμα «1» και «3» παρεμβάλλονται με τα δύο αντικείμενα.
Παραγωγή:
Thread-0 adds 0 to 10 to get -> 10 Thread-2 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-2 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-3 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-3 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63 Thread-3 adds 41 to 22 to get -> 63
Ίδιος κώδικας χρησιμοποιώντας συγχρονισμένη στατική μέθοδο
class MathService { synchronized static void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Εκτελέστε τον παραπάνω κώδικα και σημειώστε ότι έχουμε πλέον εξαλείψει τις παρεμβολές νημάτων. Η έξοδος του κώδικα φαίνεται παρακάτω.
Παραγωγή:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-3 adds 0 to 20 to get -> 20 Thread-3 adds 20 to 21 to get -> 41 Thread-3 adds 41 to 22 to get -> 63 Thread-2 adds 0 to 10 to get -> 10 Thread-2 adds 10 to 11 to get -> 21 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Πλεονεκτήματα της χρήσης του συγχρονισμού
Ακολουθούν τα πλεονεκτήματα κατά την εργασία με ταυτόχρονες εφαρμογές:
- Ο κύριος στόχος του συγχρονισμού σε Java είναι η αποτροπή ασυνεπών δεδομένων αποτρέποντας παρεμβολές νημάτων.
- Η συγχρονισμένη λέξη-κλειδί σε Java παρέχει κλείδωμα, το οποίο εξασφαλίζει αμοιβαία αποκλειστική πρόσβαση στον κοινόχρηστο πόρο και αποτρέπει τον αγώνα δεδομένων.
- Αποτρέπει επίσης την αναδιάταξη των δηλώσεων κώδικα από το μεταγλωττιστής, το οποίο μπορεί να προκαλέσει ένα ανεπαίσθητο ταυτόχρονο πρόβλημα εάν δεν χρησιμοποιήσουμε ασταθείς ή συγχρονισμένες λέξεις-κλειδιά.
- SyncΗ συγχρονισμένη λέξη-κλειδί διαβάζει δεδομένα από την κύρια μνήμη από την προσωρινή μνήμη και όταν απελευθερώνει το κλείδωμα.
- Επίσης, ξεπλένει τις λειτουργίες εγγραφής από την κύρια μνήμη, εξαλείφοντας τα σφάλματα ασυνέπειας της μνήμης.
Μειονεκτήματα του SyncΜηχανισμός Χρονισμού
SyncΧρονισμός Οι μηχανισμοί έχουν κακή απόδοση.
Για παράδειγμα
- Ας υποθέσουμε ότι υπάρχουν πέντε διαδικασίες, A1, A2, A3, A4 και A5.
- Περιμένουν τους κοινόχρηστους πόρους να έχουν πρόσβαση σε ένα νήμα τη φορά.
- Όλες οι διεργασίες παραμένουν σε αναμονή, επομένως η τελευταία στην ουρά πρέπει να περιμένει μέχρι να ολοκληρωθούν όλες οι άλλες διεργασίες.
Σύνοψη
- SyncΤο hronization αναφέρεται στην ικανότητα ελέγχου της πρόσβασης πολλαπλών νημάτων σε οποιονδήποτε κοινόχρηστο πόρο.
- Java έχει δύο τύπους μεθόδων συγχρονισμού: 1) Συγχρονισμός διεργασιών και 2) Συγχρονισμός νημάτων.
- Κλειδώσει Java είναι χτισμένο γύρω από μια εσωτερική οντότητα γνωστή ως οθόνη ή κλειδαριά.
- Ένα πρόγραμμα πολλαπλών νημάτων είναι μια μέθοδος ή μπλοκ που προστατεύεται από παρεμβολές από άλλα νήματα που μοιράζονται τον ίδιο πόρο που υποδεικνύεται χρησιμοποιώντας τη λέξη-κλειδί «συγχρονισμένο».
- Οποιαδήποτε μέθοδος δηλώνεται ως συγχρονισμένη είναι γνωστή ως συγχρονισμένη μέθοδος.
- In Java, οι κλειδαριές συγχρονισμένης μεθόδου είναι προσβάσιμες στη μέθοδο, ενώ οι κλειδαριές συγχρονισμένων μπλοκ προσπελάζονται στο αντικείμενο.
- Στον στατικό συγχρονισμό, η πρόσβαση κλειδώματος είναι στην κλάση, όχι στο αντικείμενο και τη μέθοδο.
- Ο κύριος στόχος του συγχρονισμού σε Java είναι η αποτροπή ασυνεπών δεδομένων αποτρέποντας παρεμβολές νημάτων.
- Το μεγαλύτερο μειονέκτημα αυτής της μεθόδου είναι ότι όλες οι διεργασίες διατηρούνται σε αναμονή, επομένως οι τελευταίες στην ουρά πρέπει να περιμένουν μέχρι να ολοκληρωθούν όλες οι άλλες διεργασίες.