Προγραμματισμός

Βέλτιστες πρακτικές για συγχρονισμό .Net thread

Ο συγχρονισμός είναι μια έννοια που χρησιμοποιείται για να αποτρέψει την ταυτόχρονη πρόσβαση σε πολλά νήματα σε έναν κοινόχρηστο πόρο. Μπορείτε να το χρησιμοποιήσετε για να αποτρέψετε την ταυτόχρονη επίκληση πολλών νημάτων από τις ιδιότητες ή τις μεθόδους ενός αντικειμένου. Το μόνο που χρειάζεται να κάνετε είναι να συγχρονίσετε το μπλοκ του κώδικα που έχει πρόσβαση στον κοινόχρηστο πόρο ή να συγχρονίσετε τις κλήσεις προς τις ιδιότητες και τα μέλη του αντικειμένου, ώστε σε οποιαδήποτε δεδομένη χρονική στιγμή μόνο ένα νήμα να μπορεί να εισέλθει στην κρίσιμη ενότητα.

Αυτό το άρθρο παρουσιάζει μια συζήτηση σχετικά με τις έννοιες που σχετίζονται με το συγχρονισμό και την ασφάλεια των νήματος στο .Net και τις βέλτιστες πρακτικές.

Αποκλειστική κλειδαριά

Το αποκλειστικό κλείδωμα χρησιμοποιείται για να διασφαλίσει ότι σε οποιαδήποτε δεδομένη χρονική στιγμή, ένα και μόνο ένα νήμα μπορεί να εισέλθει σε μια κρίσιμη ενότητα. Πρέπει να χρησιμοποιήσετε ένα από τα παρακάτω για να εφαρμόσετε αποκλειστικές κλειδαριές στην εφαρμογή σας.

  • Κλείδωμα - αυτή είναι μια συντακτική συντόμευση για τις στατικές μεθόδους της κλάσης Monitor και χρησιμοποιείται για την απόκτηση αποκλειστικού κλειδώματος σε έναν κοινόχρηστο πόρο
  • Mutex - παρόμοια με τη λέξη κλειδί κλειδώματος εκτός από το ότι μπορεί να λειτουργήσει σε πολλές διαδικασίες
  • SpinLock - χρησιμοποιείται για την απόκτηση αποκλειστικής κλειδαριάς σε έναν κοινόχρηστο πόρο, αποφεύγοντας το γενικό διακόπτη περιβάλλοντος νήματος

Μπορείτε να χρησιμοποιήσετε τις στατικές μεθόδους της κλάσης Παρακολούθηση ή τη λέξη-κλειδί κλειδώματος για να εφαρμόσετε την ασφάλεια του νήματος στις εφαρμογές σας. Τόσο τα στατικά μέλη της κλάσης Monitor όσο και οι λέξεις-κλειδιά κλειδώματος μπορούν να χρησιμοποιηθούν για την αποτροπή ταυτόχρονης πρόσβασης σε κοινόχρηστο πόρο. Η λέξη κλειδί κλειδώματος είναι απλώς ένας τρόπος συντόμευσης για τον συγχρονισμό. Ωστόσο, όταν πρέπει να εκτελέσετε πολύπλοκες λειτουργίες σε μια εφαρμογή πολλαπλών νημάτων, οι μέθοδοι Wait () και Pulse () της κλάσης Monitor μπορεί να είναι χρήσιμες.

Το παρακάτω απόσπασμα κώδικα δείχνει πώς μπορείτε να εφαρμόσετε συγχρονισμό χρησιμοποιώντας την κλάση Monitor.

ιδιωτικό στατικό αντικείμενο μόνο για ανάγνωση lockObj = νέο αντικείμενο ();

       static void Main (συμβολοσειρά [] args)

        {

Monitor.Enter (lockObj);

                       δοκιμάστε

            {

// Κάποιος κωδικός

            }

            τελικά

            {

Monitor.Exit (lockObj);

            }

        }

Ο ισοδύναμος κωδικός που χρησιμοποιεί τη λέξη κλειδί κλειδώματος θα μοιάζει με αυτόν:

    ιδιωτικό στατικό αντικείμενο μόνο για ανάγνωση lockObj = νέο αντικείμενο ();

static void Main (συμβολοσειρά [] args)

        {  

δοκιμάστε

            {

κλειδαριά (lockObj)

                {

// Κάποιος κωδικός

                }             

            }

τελικά

            {

// Μπορείτε να αποδεσμεύσετε τυχόν πόρους εδώ

            }

        }

Μπορείτε να επωφεληθείτε από την κλάση Mutex για να εφαρμόσετε συγχρονισμό που μπορεί να εκτείνεται σε όλες τις διαδικασίες. Σημειώστε ότι παρόμοια με τη δήλωση κλειδώματος, ένα κλείδωμα που αποκτήθηκε από ένα Mutex μπορεί να απελευθερωθεί μόνο από το ίδιο νήμα που χρησιμοποιήθηκε για την απόκτηση του κλειδώματος. Η απόκτηση και η απελευθέρωση κλειδαριών χρησιμοποιώντας το Mutex είναι συγκριτικά πιο αργή από το να κάνετε το ίδιο χρησιμοποιώντας τη δήλωση κλειδώματος.

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

Μη αποκλειστική κλειδαριά

Μπορείτε να επωφεληθείτε από το μη αποκλειστικό κλείδωμα για να περιορίσετε την ταυτόχρονη σύνδεση. Για να εφαρμόσετε μη αποκλειστικές κλειδαριές, μπορείτε να χρησιμοποιήσετε ένα από τα παρακάτω.

  • Semaphore - χρησιμοποιείται για τον περιορισμό του αριθμού των νημάτων που μπορούν να έχουν ταυτόχρονα πρόσβαση σε έναν κοινόχρηστο πόρο. Στην ουσία, χρησιμοποιείται για τον ταυτόχρονο περιορισμό του αριθμού των καταναλωτών για έναν συγκεκριμένο κοινόχρηστο πόρο.
  • SemaphoreSlim - μια γρήγορη, ελαφριά εναλλακτική λύση στην κατηγορία Semaphore για την εφαρμογή μη αποκλειστικών κλειδαριών.
  • ReaderWriterLockSlim - η κλάση ReaderWriterLockSlim εισήχθη στο .Net Framework 3.5 ως αντικατάσταση της κλάσης ReaderWriterLock.

Μπορείτε να χρησιμοποιήσετε την τάξη ReaderWriterLockSlim για να αποκτήσετε ένα μη αποκλειστικό κλείδωμα σε έναν κοινόχρηστο πόρο που θα χρειαζόταν συχνές αναγνώσεις αλλά σπάνιες ενημερώσεις. Έτσι, αντί για ένα αποκλειστικό κλείδωμα σε έναν κοινόχρηστο πόρο που χρειάζεται συχνές αναγνώσεις και σπάνιες ενημερώσεις, μπορείτε να χρησιμοποιήσετε αυτήν την τάξη για να αποκτήσετε ένα κλείδωμα ανάγνωσης στον κοινόχρηστο πόρο και ένα αποκλειστικό κλείδωμα εγγραφής σε αυτόν.

Αδιέξοδα

Θα πρέπει να αποφύγετε τη χρήση δήλωσης κλειδώματος στον τύπο ή να χρησιμοποιήσετε δηλώσεις όπως κλείδωμα (αυτό) για να εφαρμόσετε συγχρονισμό στην εφαρμογή σας, καθώς αυτό μπορεί να οδηγήσει σε αδιέξοδα. Σημειώστε ότι τα αδιέξοδα μπορούν επίσης να προκύψουν εάν κρατάτε το κλείδωμα που αποκτήθηκε σε έναν κοινόχρηστο πόρο για μεγαλύτερο χρονικό διάστημα. Δεν πρέπει να χρησιμοποιείτε αμετάβλητους τύπους στις δηλώσεις κλειδώματος. Για παράδειγμα, θα πρέπει να αποφύγετε να χρησιμοποιήσετε ένα αντικείμενο συμβολοσειράς ως κλειδί στη δήλωση κλειδώματος. Θα πρέπει να αποφύγετε τη χρήση της δήλωσης κλειδώματος σε δημόσιο τύπο - είναι καλή πρακτική να κλειδώνετε ιδιωτικά ή προστατευμένα αντικείμενα που δεν είναι εσωτερικά. Στην ουσία, μια κατάσταση αδιεξόδου εμφανίζεται όταν πολλά νήματα περιμένουν το ένα το άλλο για να απελευθερώσουν το κλείδωμα σε έναν κοινόχρηστο πόρο. Μπορείτε να ανατρέξετε σε αυτό το άρθρο MSDN για να μάθετε περισσότερα σχετικά με τα αδιέξοδα.

$config[zx-auto] not found$config[zx-overlay] not found