Στην Java, οι άλλες βασικές μεταβλητές είναι ατομικές, εκτός από τις μεταβλητές 8 byte, 64 bit του Long και του Double.
Το μοντέλο αποθήκευσης Java απαιτεί τόσο οι λειτουργίες λήψης όσο και αποθήκευσης να είναι ατομικές, αλλά για μη πτητικές μακρές και διπλές μεταβλητές, το JVM επιτρέπει τον διαχωρισμό μιας ανάγνωσης ή εγγραφής 64-bit σε δύο λειτουργίες 32-bit.
Εάν η ανάγνωση και η εγγραφή πραγματοποιούνται σε διαφορετικά νήματα, η ανάγνωση ενός μη πτητικού τύπου μπορεί να έχει ως αποτέλεσμα υψηλά 32 bit της μίας τιμής και χαμηλά 32 bit της άλλης.
Έτσι, ακόμα κι αν δεν σας ενδιαφέρουν τα δεδομένα που έχουν λήξει, μπορεί να μην είναι ασφαλές να χρησιμοποιήσετε κοινόχρηστες, μεταβλητές μακρές και διπλές μεταβλητές σε ένα πρόγραμμα πολλαπλών νημάτων, εκτός εάν δηλωθούν ως πτητικές ή προστατεύονται με κλείδωμα.
Μιλώντας για ατομικές πράξεις, σημαίνει ότι η ανάγνωση και η γραφή είναι ατομικές, όπως i=5. Αυτή είναι μια ατομική επιχείρηση.
Ωστόσο, εάν η λειτουργία δύο ατόμων πραγματοποιείται μαζί, δεν είναι απαραίτητα ατομική, όπως η ανάγνωση πρώτα και μετά η γραφή, τότε είναι πιθανό η μεταβλητή να έχει τροποποιηθεί μετά την ανάγνωση.
Το i++ είναι μια τέτοια πράξη, διαβάστε πρώτα και μετά γράψτε, οπότε η ακέραια μεταβλητή είναι ατομική, όχι ότι το i++ είναι ατομική πράξη.
Όταν χρησιμοποιείτε for(int i=0; Ι<10000; i++){System.out.print(i)}
Θα διαπιστώσετε ότι δεν θα εκτυπώσω 10.000 στο τέλος, και θα εκτυπώσω περίπου 8-9 χιλιάδες.
Αλλά στην περίπτωση πολλαπλών νημάτων, ακόμα κι αν η ακέραια μεταβλητή είναι ατομική, μπορεί να υπάρχουν προβλήματα ασφάλειας νήματος, κάτι που είναι πρόβλημα ορατότητας νήματος, επομένως πρέπει να προσθέσετε μια ασταθή δήλωση.
Αυτός ο τροποποιητής είναι μια αναγκαστική μεταβλητή που διαβάζεται από τη μνήμη κάθε φορά και δεν αποθηκεύεται σε καταχωρητές. |