سؤال

لقد لاحظت أنه يمكنك الاتصال بـ Queue.Synchronize للحصول على كائن قائمة انتظار آمن لمؤشر الترابط، ولكن نفس الطريقة غير متوفرة في Queue<T>.هل يعرف أحد لماذا؟يبدو غريبا نوعا ما.

هل كانت مفيدة؟

المحلول

تحديث - في .NET 4، يوجد الآن ConcurrentQueue<T> في System.Collections.Concurrent، كما هو موثق هنا http://msdn.microsoft.com/en-us/library/dd267265.aspx.من المثير للاهتمام ملاحظة أن طريقة IsSynchronized الخاصة بها (بحق) تُرجع خطأ.

ConcurrentQueue<T> عبارة عن إعادة كتابة كاملة من البداية إلى النهاية، وإنشاء نسخ من قائمة الانتظار للتعداد، واستخدام تقنيات عدم القفل المتقدمة مثل Interlocked.CompareExchange() و Thread.SpinWait().

لا تزال بقية هذه الإجابة ذات صلة بقدر ما تتعلق بزوال أعضاء Synchronize() وSyncRoot القديمين، ولماذا لم يعملوا بشكل جيد من منظور واجهة برمجة التطبيقات.


وفقًا لتعليق Zooba، قرر فريق BCL أن الكثير من المطورين يسيئون فهم الغرض من المزامنة (وبدرجة أقل، SyncRoot)

وصف برايان جرونكيماير هذا الأمر في مدونة فريق BCL قبل عامين:http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx

تكمن المشكلة الرئيسية في الحصول على التفاصيل الصحيحة حول الأقفال، حيث قد يستخدم بعض المطورين بسذاجة خصائص أو طرق متعددة في مجموعة "متزامنة" ويعتقدون أن التعليمات البرمجية الخاصة بهم آمنة للسلسلة.يستخدم براين قائمة الانتظار كمثال له،

if (queue.Count > 0) {
    object obj = null;
    try {
        obj = queue.Dequeue();

لن يدرك المطورون أنه يمكن تغيير Count بواسطة مؤشر ترابط آخر قبل استدعاء Dequeue.

إن إجبار المطورين على استخدام عبارة قفل صريحة حول العملية بأكملها يعني منع هذا الشعور الزائف بالأمان.

كما يذكر براين، فإن إزالة SyncRoot ترجع جزئيًا إلى أنه تم تقديمه بشكل أساسي لدعم المزامنة، ولكن أيضًا لأنه في كثير من الحالات يكون هناك اختيار أفضل لكائن القفل - في معظم الأحيان، إما مثيل قائمة الانتظار نفسها، أو

private static object lockObjForQueueOperations = new object();

في الفصل الذي يمتلك مثيل قائمة الانتظار ...

عادةً ما يكون هذا النهج الأخير هو الأكثر أمانًا لأنه يتجنب بعض الفخاخ الشائعة الأخرى:

كما يقولون، خيوط صعبة, ، وجعل الأمر يبدو سهلاً يمكن أن يكون خطيرًا.

نصائح أخرى

قد تجد برنامج Parallel CTP يستحق التدقيق عليه؛إليك إدخال مدونة من الأشخاص الذين قاموا بتجميعه وهو أمر موضوعي جدًا:

تعداد المجموعات المتزامنة

إنه ليس نفس الشيء تمامًا، ولكنه قد يحل مشكلتك الأكبر.(حتى أنهم يستخدمون Queue<T> عكس ConcurrentQueue<T> كمثال لهم.)

يوجد واحد الآن في .Net 4.0:

ConcurrentQueue<T> 

في System.Collections.Concurrent

http://msdn.microsoft.com/en-us/library/dd267265.aspx

(أفترض أنك تقصد Queue<T> للثانية.)

لا يمكنني الإجابة على السؤال تحديدًا، باستثناء أن خصائص IsSynchronized وSyncRoot (ولكن ليس Synchronise() بشكل صريح) موروثة من واجهة ICollection.لا تستخدم أي من المجموعات العامة هذا ولا تتضمن واجهة ICollection<T> SyncRoot.

بالنسبة لسبب عدم تضمينها، لا يمكنني إلا أن أتكهن بأنها لم يتم استخدامها بالطريقة التي أرادها مصممو المكتبة أو ببساطة لم يتم استخدامها بما يكفي لتبرير الاحتفاظ بها في المجموعات الأحدث.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top