عبارة 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