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

Τα δύο σεντ μου στο SpinLock στο .Net

Φανταστείτε μια κατάσταση στην οποία ένα νήμα προσπαθεί να αποκτήσει πρόσβαση σε έναν κοινόχρηστο πόρο, αλλά ο πόρος είναι ήδη κλειδωμένος, οπότε το νήμα πρέπει να περιμένει μέχρι να απελευθερωθεί το κλείδωμα. Εδώ μπαίνει το παιχνίδι συγχρονισμού νήματος. Ο συγχρονισμός νημάτων χρησιμοποιείται για να αποτρέψει την ταυτόχρονη πρόσβαση πολλών νημάτων σε έναν κοινόχρηστο πόρο. Το Microsoft .Net Framework παρέχει υποστήριξη για μια σειρά πρωτευόντων συγχρονισμού που μπορούν να χρησιμοποιηθούν για τον έλεγχο της συμπεριφοράς του νήματος και την αποφυγή των συνθηκών αγώνα. Το Mutex και το Spinlock είναι δύο δημοφιλείς μηχανισμοί συγχρονισμού που χρησιμοποιούνται για τον συγχρονισμό της πρόσβασης σε έναν κοινόχρηστο πόρο.

Το SpinLock είναι μια εναλλακτική λύση για τον αποκλεισμό του συγχρονισμού. Το SpinLock (επίσης γνωστό ως "Busy Waiting") είναι ένας μηχανισμός που μπορεί να χρησιμοποιηθεί για να φτιάξει ένα νήμα που προσπαθεί να αποκτήσει ένα κλείδωμα αναμονής σε ένα βρόχο έως ότου μπορεί να έχει πρόσβαση στον πόρο. Σημειώστε ότι το SpinLock μπορεί να αποδώσει ταχύτερα σε σύγκριση με το Mutex, καθώς η εναλλαγή περιβάλλοντος περιορίζεται. Ωστόσο, θα πρέπει να χρησιμοποιείτε το SpinLocks μόνο εάν η κρίσιμη ενότητα υποτίθεται ότι εκτελεί ελάχιστο όγκο εργασίας, δηλαδή το SpinLock διατηρείται για πολύ σύντομο χρονικό διάστημα. Τα SpinLocks συνήθως προτιμώνται σε συμμετρικά συστήματα πολλαπλών επεξεργαστών για συνεχή δημοσκόπηση για διαθεσιμότητα ενός πόρου αντί για διακόπτες περιβάλλοντος.

Τι είναι το SpinLock και γιατί χρειάζεται;

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

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

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

Προγραμματισμός SpinLock στο .Net

Σημειώστε ότι ένα SpinLock ορίζεται ως δομή στο .Net, δηλαδή ορίζεται ως τύπος τιμής για λόγους απόδοσης. Επομένως, εάν περνάτε από μια παρουσία SpinLock, θα πρέπει να τη μεταβιβάσετε με αναφορά και όχι από αξία. Σε αυτήν την ενότητα θα διερευνήσουμε πώς μπορούμε να προγραμματίσουμε το SpinLock στο .Net. Για να εφαρμόσετε το SpinLock στο .Net, θα πρέπει να επωφεληθείτε από την κλάση SpinLock που είναι διαθέσιμη στο System.Threading namespace.

Η ακόλουθη λίστα κωδικών δείχνει πώς μπορείτε να χρησιμοποιήσετε το SpinLock στο .Net.

SpinLock spinLock = νέο SpinLock (true);

bool isLocked = false;

δοκιμάστε

{

spinLock.Enter (ref είναι κλειδωμένο);

// Γράψτε τον συνηθισμένο κωδικό σας εδώ

}

τελικά

{

εάν (isLocked)

spinLock.Exit ();

}

Περίμενε

Σημειώστε ότι όπως το SpinLock, το SpinWait είναι επίσης δομή και όχι τάξη. Παρόμοια με το SpinLock, μπορείτε να χρησιμοποιήσετε το SpinWait για να γράψετε κώδικα συγχρονισμού χωρίς κλειδώματα που μπορεί να "περιστραφεί" αντί να μπλοκάρει. Το SpinWait μπορεί να χρησιμοποιηθεί για τη μείωση της κατανάλωσης πόρων εκτελώντας εντατική περιστροφή CPU για 10 επαναλήψεις μετά την οποία θα δώσει τον έλεγχο καλώντας το Thread.Yield και το Thread.Sleep. Με άλλα λόγια, το SpinWait μπορεί να χρησιμοποιηθεί για τον περιορισμό της εντατικής περιστροφής σε CPU σε έναν καθορισμένο αριθμό επαναλήψεων. Το MSDN δηλώνει: "System.Threading.SpinWait είναι ένας ελαφρύς τύπος συγχρονισμού που μπορείτε να χρησιμοποιήσετε σε σενάρια χαμηλού επιπέδου για να αποφύγετε τους ακριβούς διακόπτες περιβάλλοντος και τις μεταβάσεις πυρήνα που απαιτούνται για συμβάντα πυρήνα."

Για να χρησιμοποιήσετε το SpinWait στον κώδικά σας, μπορείτε είτε να χρησιμοποιήσετε τη στατική μέθοδο SpinUntil () της δομής SpinWait είτε να επωφεληθείτε από τη μη στατική μέθοδο SpinOnce (). Το παρακάτω απόσπασμα κώδικα δείχνει πώς μπορεί να χρησιμοποιηθεί το SpinWait.

SpinWait spinWait = νέο SpinWait ();

bool shouldSpin;

ενώ (! shouldSpin)

{

Thread.MemoryBarrier (); spinWait.SpinOnce ();

}

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