مشاركة عبر


كيفية القيام بما يلي: تمكين مؤشر ترابط-تتبع الوضع في تأمين لوصول فردي

System.Threading.SpinLockهو قفل الاستثنائي متبادلة ذات المستوى منخفض التي يمكن استخدم للسيناريوهات التي تحتوي على مرة/مرات الانتظار قصير جداً. SpinLockهو لا re-entrant. بعد مؤشر ترابط Enter الزر s التأمين، فإنه يجب إنهاء التأمين بشكل صحيح حتى يمكن Enter الزر مرة أخرى. بشكل عام، أي محاولة إلى re-Enter الزر التأمين يؤدي حالة توقف تام، ويمكن أن تكون deadlocks صعبة جداً إلى التصحيح. أي مساعدة للتطوير، System.Threading.SpinLockيعتمد الوضع تعقب مسار التنفيذ الذي يتسبب في حدوث استثناء أن يتم طرح عندما يحاول مؤشر ترابط لإعادة التشغيل Enter الزر بقفل أنه الفعل قوائم احتجاز. يتيح هذا إمكانية أكثر بسهولة بحث النقطة التي عندها قفل لا تم إنهاء بشكل صحيح. يمكنك تشغيل الوضع تعقب مؤشر ترابط باستخدام SpinLockالمنشئ تأخذ قيمة منطقية بإدخال معلمة، و تمرير في وسيطة من true. بعد الانتهاء من التطوير و مراحل الاختبار، أوقف تشغيل الوضع تعقب مؤشر ترابط لتحقيق أداء أفضل.

مثال

يوضح المثال التالي مؤشر ترابط-تتبع الوضع. تم التعليق على الأسطر التي إنهاء التأمين بشكل صحيح عن إلى محاكاة خطأ ترميز تؤدي إحدى نتائج التالية:

  • استثناء هو لو تم طرح SpinLockتم إنشاؤه باستخدام وسيطة من true(Trueفي Vهوual أساسى).

  • حالة توقف تام إذا SpinLockانشئت بواسطة استخدام وسيطة من false(Falseفي Visual أساسى).

Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks
Module Module1

    Public Class SpinTest

        ' True means "enable thread tracking." This will cause an
        ' exception to be thrown when the first thread attempts to reenter the lock.
        ' Specify False to cause deadlock due to coding error below.
        Private Shared _spinLock = New SpinLock(True)

        Public Shared Sub Main()

            Parallel.Invoke(
                Sub() DoWork(),
                Sub() DoWork(),
                Sub() DoWork(),
                Sub() DoWork()
                )

            Console.WriteLine("Press any key.")
            Console.ReadKey()
        End Sub

        Public Shared Sub DoWork()

            Dim sb = New StringBuilder()

            For i As Integer = 1 To 9999

                Dim lockTaken As Boolean = False

                Try
                    _spinLock.Enter(lockTaken)

                    ' do work here protected by the lock
                    Thread.SpinWait(50000)
                    sb.Append(Thread.CurrentThread.ManagedThreadId)
                    sb.Append(" Entered-")

                Catch ex As LockRecursionException
                    Console.WriteLine("Thread {0} attempted to reenter the lock",
                                       Thread.CurrentThread.ManagedThreadId)
                    Throw

                Finally

                    ' INTENTIONAL CODING ERROR TO DEMONSTRATE THREAD TRACKING! 
                    ' UNCOMMENT THE LINES FOR CORRECT SPINLOCK BEHAVIOR
                    ' Commenting out these lines causes the same thread
                    ' to attempt to reenter the lock. If the SpinLock was
                    ' created with thread tracking enabled, the exception
                    ' is thrown. Otherwise, if the SpinLock was created with a 
                    ' parameter of false, and these lines are left commented, the spinlock deadlocks.
                    If (lockTaken) Then

                        '  _spinLock.Exit()
                        '  sb.Append("Exited ")
                    End If
                End Try

                ' Output for diagnostic display.
                If (i Mod 4 <> 0) Then
                    Console.Write(sb.ToString())
                Else
                    Console.WriteLine(sb.ToString())
                End If
                sb.Clear()
            Next
        End Sub
    End Class
End Module
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SpinLockDemo
{
    // C#‎
    public class SpinLockTest
    {
        // Specify true to enable thread tracking. This will cause
        // exception to be thrown when the first thread attempts to reenter the lock.
        // Specify false to cause deadlock due to coding error below.
        private static SpinLock _spinLock = new SpinLock(true);

        static void Main()
        {
            Parallel.Invoke(
                () => DoWork(),
                () => DoWork(),
                () => DoWork(),
                () => DoWork()
                );

            Console.WriteLine("Press any key.");
            Console.ReadKey();
        }

        public static void DoWork()
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 100; i++)
            {

                bool lockTaken = false;

                try
                {
                    _spinLock.Enter(ref lockTaken);

                    // do work here protected by the lock
                    Thread.SpinWait(50000);
                    sb.Append(Thread.CurrentThread.ManagedThreadId);
                    sb.Append(" Entered-");
                }
                catch (LockRecursionException ex)
                {
                    Console.WriteLine("Thread {0} attempted to reenter the lock",
                                       Thread.CurrentThread.ManagedThreadId);
                    throw;
                }
                finally
                {
                    // INTENTIONAL CODING ERROR TO DEMONSTRATE THREAD TRACKING! 
                    // UNCOMMENT THE LINES FOR CORRECT SPINLOCK BEHAVIOR
                    // Commenting out these lines causes the same thread
                    // to attempt to reenter the lock. If the SpinLock was
                    // created with thread tracking enabled, the exception
                    // is thrown. Otherwise the spinlock deadlocks.
                    if (lockTaken)
                    {
                       // _spinLock.Exit(false);
                       // sb.Append("Exited ");
                    }
                }

                // Output for diagnostic display.
                if(i % 4 != 0)
                    Console.Write(sb.ToString());
                else
                    Console.WriteLine(sb.ToString());
                sb.Clear();

            }
        }
    }
}

راجع أيضًا:

موارد أخرى

تأمين لوصول فردي