Η έννοια των κλειδαριών ανάγνωσης-εγγραφής είναι απλή, επιτρέποντας σε πολλά νήματα να αποκτούν κλειδαριές ανάγνωσης ταυτόχρονα, αλλά μόνο ένα νήμα επιτρέπεται να αποκτά κλειδαριές εγγραφής ταυτόχρονα, επομένως ονομάζεται επίσης κοινόχρηστες-αποκλειστικές κλειδαριές. Στη C#, συνιστάται η χρήση της κλάσης ReaderWriterLockSlim για την ολοκλήρωση της λειτουργίας κλειδώματος ανάγνωσης/εγγραφής. Σε ορισμένες περιπτώσεις, ο αριθμός των αναγνώσεων σε ένα αντικείμενο είναι πολύ μεγαλύτερος από τον αριθμό των τροποποιήσεων και εάν απλώς κλειδωθεί με κλείδωμα, θα επηρεάσει την αποτελεσματικότητα της ανάγνωσης. Εάν χρησιμοποιείται κλείδωμα ανάγνωσης-εγγραφής, πολλά νήματα μπορούν να διαβάσουν το αντικείμενο ταυτόχρονα και θα αποκλειστεί μόνο όταν το αντικείμενο καταλαμβάνεται από το κλείδωμα εγγραφής. Με απλά λόγια, όταν ένα νήμα εισέρχεται σε λειτουργία ανάγνωσης, άλλα νήματα μπορούν ακόμα να εισέλθουν σε λειτουργία ανάγνωσης, υποθέτοντας ότι ένα νήμα θέλει να εισέλθει σε λειτουργία εγγραφής αυτή τη στιγμή, τότε πρέπει να αποκλειστεί. μέχρι να βγει η λειτουργία ανάγνωσης. Ομοίως, εάν ένα νήμα μεταβεί σε λειτουργία εγγραφής, τα άλλα νήματα θα αποκλειστούν είτε θέλουν να γράψουν είτε να διαβάσουν. Υπάρχουν 2 τρόποι για να μπείτε στη λειτουργία εγγραφής/ανάγνωσης: Το EnterReadLock επιχειρεί να εισέλθει στην κατάσταση κλειδώματος λειτουργίας εγγραφής. TryEnterReadLock(Int32) επιχειρεί να εισέλθει στην κατάσταση κλειδώματος λειτουργίας ανάγνωσης, με την επιλογή επιλογής ακέραιου χρονικού ορίου. EnterWriteLock επιχειρεί να εισέλθει στην κατάσταση κλειδώματος λειτουργίας εγγραφής. TryEnterWriteLock(Int32) επιχειρεί να εισέλθει στην κατάσταση κλειδώματος λειτουργίας εγγραφής και μπορεί να επιλεγεί ο χρόνος χρονικού ορίου. Υπάρχουν 2 τρόποι για έξοδο από τη λειτουργία εγγραφής/ανάγνωσης: Το ExitReadLock μειώνει τον αναδρομικό αριθμό της λειτουργίας ανάγνωσης και εξέρχεται από τη λειτουργία ανάγνωσης όταν ο αριθμός που προκύπτει είναι 0 (μηδέν). Το ExitWriteLock μειώνει το αναδρομικό πλήθος του μοτίβου εγγραφής και εξέρχεται από τη λειτουργία εγγραφής όταν το πλήθος που προκύπτει είναι 0 (μηδέν). Δείτε πώς να το χρησιμοποιήσετε:
Μπορείτε να δείτε ότι το νήμα 3 και το νήμα 4 μπορούν να εισέλθουν σε λειτουργία ανάγνωσης ταυτόχρονα, ενώ το νήμα 5 μπορεί να εισέλθει σε λειτουργία εγγραφής μετά από 5 δευτερόλεπτα (δηλαδή, αφού τα νήματα 3 και 4 βγουν από το κλείδωμα ανάγνωσης). Τροποποιήστε τον παραπάνω κώδικα, ανοίξτε πρώτα 2 νήματα σε λειτουργία εγγραφής και, στη συνέχεια, ανοίξτε νήματα σε λειτουργία ανάγνωσης, ο κώδικας έχει ως εξής:
Τα αποτελέσματα έχουν ως εξής:
Όπως μπορείτε να δείτε, το νήμα 3 και το νήμα 4 εισέρχονται και τα δύο σε λειτουργία εγγραφής, αλλά το νήμα 3 καταλαμβάνει πρώτα το κλείδωμα εγγραφής, επομένως το νήμα 4 πρέπει να περιμένει 10 δευτερόλεπτα πριν εισέλθει. Τα νήματα 5 και 6 πρέπει να καταλαμβάνουν το κλείδωμα ανάγνωσης, επομένως περιμένετε μέχρι το νήμα 4 να βγει από το κλείδωμα εγγραφής πριν συνεχίσετε. Το TryEnterReadLock και το TryEnterWriteLock μπορούν να ορίσουν ένα χρονικό όριο, όταν εκτελείται σε αυτήν την πρόταση, το νήμα θα μπλοκάρει εδώ, εάν η κλειδαριά μπορεί να καταληφθεί αυτήν τη στιγμή, τότε επιστρέψτε true, εάν ο χρόνος χρονικού ορίου δεν έχει καταλάβει ακόμη την κλειδαριά, στη συνέχεια επιστρέψτε false, εγκαταλείψτε την κατοχή της κλειδαριάς και συνεχίστε να εκτελείτε απευθείας τον ακόλουθο κώδικα. EnterUpgradeableReadLock Η κλάση ReaderWriterLockSlim παρέχει μια αναβαθμίσιμη λειτουργία ανάγνωσης, η οποία διαφέρει από τη λειτουργία ανάγνωσης στο ότι μπορεί επίσης να αναβαθμιστεί σε λειτουργία εγγραφής καλώντας τις μεθόδους EnterWriteLock ή TryEnterWriteLock. Επειδή μόνο ένα νήμα μπορεί να είναι σε λειτουργία αναβάθμισης κάθε φορά. Ένα νήμα που εισέρχεται σε λειτουργία αναβάθμισης δεν θα επηρεάσει το νήμα σε λειτουργία ανάγνωσης, δηλαδή, όταν ένα νήμα εισέρχεται σε λειτουργία αναβάθμισης, οποιοσδήποτε αριθμός νημάτων μπορεί να εισέλθει σε λειτουργία ανάγνωσης ταυτόχρονα χωρίς αποκλεισμό. Εάν πολλά νήματα περιμένουν ήδη να αποκτήσουν ένα κλείδωμα εγγραφής, η εκτέλεση του EnterUpgradeableReadLock θα αποκλείσει μέχρι να λήξει το χρονικό όριο αυτών των νημάτων ή να βγει από το κλείδωμα εγγραφής. Ο παρακάτω κώδικας δείχνει πώς να κάνετε αναβάθμιση σε κλείδωμα εγγραφής σε λειτουργία ανάγνωσης με δυνατότητα αναβάθμισης.
Ο αντίκτυπος των κλειδωμάτων ανάγνωσης/εγγραφής στην απόδοση είναι προφανής. Ο ακόλουθος κωδικός δοκιμής:
Ο παραπάνω κώδικας προσομοιώνει τη λειτουργία 500 εργασιών, καθεμία από τις οποίες καταλαμβάνει ένα νήμα συγκέντρωσης νημάτων, εκ των οποίων οι 20 είναι νήματα εγγραφής και τα 480 νήματα ανάγνωσης προσομοιώνονται. Χρειάζονται 10 ms για την ανάγνωση δεδομένων και 100 ms για την εγγραφή για να δοκιμαστεί η μέθοδος κλειδώματος και η μέθοδος ReaderWriterLockSlim αντίστοιχα. Μπορεί να γίνει μια εκτίμηση, για το ReaderWriterLockSlim, υποθέτοντας ότι 480 νήματα διαβάζονται ταυτόχρονα, τότε καταναλώνει 10ms, 20 λειτουργίες εγγραφής καταλαμβάνουν 2000ms, οπότε ο χρόνος που καταναλώνεται είναι 2010ms και για τη συνηθισμένη μέθοδο κλειδώματος, επειδή είναι όλες αποκλειστικές, επομένως 480 λειτουργίες ανάγνωσης καταλαμβάνουν 4800ms + 20 λειτουργίες εγγραφής 2000ms = 6800ms. Τα αποτελέσματα έδειξαν αξιοσημείωτη βελτίωση της απόδοσης.
|