عبارة SyncLock

تكتسب قفل حصري على كتلة العبارة قبل تنفيذ الكتلة.

SyncLock lockobject
    [ block ]
End SyncLock

الأجزاء

  • lockobject
    مطلوبة. تعبير تقيّم إلى مرجع كائن.

  • block
    اختياري. كتلة من العبارات يتم تنفيذها عندما يتم الحصول على التأمين.

  • End SyncLock
    تنهي كتلة SyncLock.

ملاحظات

عبارة SyncLock يضمن أن مؤشرات ترابط متعددة لا تنّفذ كتلة العبارة في نفس الوقت. SyncLock يمنع كل مؤشر ترابط من إدخال الكتلة حتى لا يبقى تنفيذ أي مؤشر ترابط.

الاستخدام الأكثر شيوعاً SyncLock هو ليحمي البيانات من التحديث من قبل أكثر من مؤشر ترابط واحد في نفس الوقت. إذا كان يجب أن تنتقل العبارات التي تعالج بيانات إلى الاكتمال دون مقاطعة ، ضعها داخل كتلة SyncLock.

كتلة العبارة محمية بواسطة قفل خاص أحياناً تسمى مقطع حرج.

القواعد

  • التفريع. لا يمكن التفرع في كتلة SyncLock من خارج الكتلة.

  • قيمة كائن القفل. القيمة lockobject لا يمكن Nothing. يجب عليك إنشاء كائن قفل قبل استخدامه في العبارة SyncLock.

    لا يمكنك تغيير قيمة lockobject أثناء تنفيذ كتلة SyncLock. تتطلب الآلية أنّ قفل الكائن تبقى بدون تغيير.

السلوك

  • آلية. عند وصول مؤشر ترابط إلى عبارة SyncLock هي تقيّم تعبير lockobject ويوقف التنفيذ مؤقتا حتى تكتسب قفل خاص على كائن تم إرجاعه بواسطة التعبير. عند وصول مؤشر ترابط آخر إلى عبارة SyncLock لا تحصل على قفل حتى ينفّذ أول مؤشر الترابط العبارة End SyncLock.

  • بيانات محمية. إذا lockobject هو متغير Shared ، القفل الخاص يمنع مؤشر ترابط في أي مثيل فئة من تنفيذ كتلة SyncLock أثناء تنفيذ أي مؤشر أخر. هذا يحمي البيانات التي يتم مشاركتها بين كل المثيلات.

    إذا كان متغير مثيل lockobject (ليس Shared) ، القفل يمنع مؤشر الترابط قيد التشغيل في المثيل الحالي من تنفيذ كتلة SyncLock في نفس وقت مؤشر ترابط آخر في نفس المثيل. هذا يحمي البيانات بالاحتفاظ من مثيل فردي.

  • الحصول و يطرح المنتج. كتلة SyncLock يسلك الإنشاء Try...Finally فيه Try تكتسب كتلة قفل خاص على lockobject و كتلة Finally الإصدارات عليها. لهذا السبب، كتلة SyncLock يضمن إصدار قفل بغض النظر عن كيفية إنهاء الكتلة. و يكون هذا صحيحاً حتى في حالة الاستثناء غير المعالج.

  • Framework المكالمات. الكتلة SyncLock تكتسب وتحرر قفل خاص للاستخدام عن طريق استدعاء Enter و أساليب Exit في فئة Monitor في مساحة الاسم System.Threading .

ممارسات البرمجة

التعبير lockobject يجب أن تقيّم دوماً كائن ينتمي إلى الفئة بشكل خاص. يجب أن تقوم بتعريف متغير الكائن Private لحماية بيانات التي تنتمي إلى المثيل الحالي, أو متغير الكائن Private Shared لحماية بيانات الشائعة لكل مثيل.

يجب عدم استخدام الكلمة الأساسية Me لتوفير قفل كائن مثيل بيانات. إذا كان التعليمة البرمجية الخارجية لفئة لديها مرجع لمثيل الفئة قد يستخدم ذلك المرجع كـ قفل كائن لكتلةـ SyncLock المختلف تمامًا عن المطلوب ، لحماية بيانات مختلفة. بهذه الطريقة، فئتك و الفئة الأخرى قد تحظر بعضها البعض من التنفيذ غير المرتبط الخاص بكتلة SyncLock. وبنفس الطريقة، الحظر على سلسلة يمكن أن بكون مشكوك حيث أنّ أي تعليمات برمجية ستشترك في نفس العملية باستخدام نفس سلسلة ستتشارك نفس القفل.

يجب أيضاً عدم استخدام أسلوب Me.GetType لتوفير كائن قفل البيانات المشتركة. وهذا لأن GetType دوماً يرجع نفس الكائن Type لاسم الفئة المعطى. قد يستدعي التعليمات البرمجية الخارجية GetType على جهاز فئة والحصول على نفس كائن التأمين الذي تستخدمه. هذا سيؤدي إلى حظر فئتين لبعضها البعض من الكتل الخاصة بهمSyncLock.

أمثلة

الوصف

يظهر المثال التالي فئة يحتفظ بقائمة بسيطة من رسائل. فإنه يحتفظ بالرسائل الموجودة في صفيف ويستخدم عنصر آخر في متغير ذلك الصفيف. الإجراء addAnotherMessage يزيد العنصر الأخير ويخزنّ الرسالة الجديدة. هذه العمليات محمية بواسطة عبارات SyncLock و End SyncLock، لأن بمجرد زيادة العنصر الأخير, يجب أن يتم تخزين الرسالة الجديدة قبل أي مؤشر ترابط آخر و يمكن زيادة عنصر الأخير مرة أخرى.

إذا كان الفئة simpleMessageList تشترك في قائمة واحدة من الرسائل بين كل حالات مجلداته، المتغيرات messagesList و messagesLast يمكن تعريفها كـ Shared. في هذه الحالة، المتغير messagesLock يجب أن تكون أيضاً Shared، بحيث يكون هناك كائن قفل مفرد مستخدمة من قبل كل مثيل.

الرمز

Class simpleMessageList
    Public messagesList() As String = New String(50) {}
    Public messagesLast As Integer = -1
    Private messagesLock As New Object
    Public Sub addAnotherMessage(ByVal newMessage As String)
        SyncLock messagesLock
            messagesLast += 1
            If messagesLast < messagesList.Length Then
                messagesList(messagesLast) = newMessage
            End If
        End SyncLock
    End Sub
End Class

الوصف

يستخدم المثال التالي عمليات جزئية و SyncLock. طالما أن العبارة SyncLock موجودة، كتلة العبارة هو مقطع حرج و balance لن يصبح رقم سالب. يمكنك التعليق خارج SyncLock و عبارات End SyncLock و لمشاهدة التأثير من ترك الكلمة الأساسية SyncLock .

الرمز

Imports System.Threading

Module Module1

    Class Account
        Dim thisLock As New Object
        Dim balance As Integer

        Dim r As New Random()

        Public Sub New(ByVal initial As Integer)
            balance = initial
        End Sub

        Public Function Withdraw(ByVal amount As Integer) As Integer
            ' This condition will never be true unless the SyncLock statement
            ' is commented out:
            If balance < 0 Then
                Throw New Exception("Negative Balance")
            End If

            ' Comment out the SyncLock and End SyncLock lines to see
            ' the effect of leaving out the SyncLock keyword.
            SyncLock thisLock
                If balance >= amount Then
                    Console.WriteLine("Balance before Withdrawal :  " & balance)
                    Console.WriteLine("Amount to Withdraw        : -" & amount)
                    balance = balance - amount
                    Console.WriteLine("Balance after Withdrawal  :  " & balance)
                    Return amount
                Else
                    ' Transaction rejected.
                    Return 0
                End If
            End SyncLock
        End Function

        Public Sub DoTransactions()
            For i As Integer = 0 To 99
                Withdraw(r.Next(1, 100))
            Next
        End Sub
    End Class

    Sub Main()
        Dim threads(10) As Thread
        Dim acc As New Account(1000)

        For i As Integer = 0 To 9
            Dim t As New Thread(New ThreadStart(AddressOf acc.DoTransactions))
            threads(i) = t
        Next

        For i As Integer = 0 To 9
            threads(i).Start()
        Next
    End Sub

End Module

راجع أيضًا:

المرجع

System.Threading

Monitor

مؤشر ترابط تجمع (C# و Visual Basic)

التأشير الترابطي ل Visual Basic و #Visual C