سؤال

لدي C# المفرد فئة فئات متعددة الاستخدام.هو الوصول من خلال Instance إلى Toggle() طريقة مؤشر الترابط-الآمن ؟ إذا كان الجواب نعم ، ما افتراضات, القواعد, إلخ.إذا كان لا لماذا و كيف يمكنني إصلاح ذلك ؟

public class MyClass
{
    private static readonly MyClass instance = new MyClass();

    public static MyClass Instance
    {
        get { return instance; }
    }

    private int value = 0;

    public int Toggle()
    {
        if(value == 0) 
        {
            value = 1; 
        }
        else if(value == 1) 
        { 
            value = 0; 
        }

        return value;
    }
}
هل كانت مفيدة؟

المحلول

هو الوصول من خلال 'المثال' إلى 'تبديل()' الفئة threadsafe?إذا كان الجواب نعم ، ما افتراضات, القواعد, إلخ.إذا كان لا لماذا و كيف يمكنني إصلاح ذلك ؟

لا, ليس threadsafe.

أساسا كل المواضيع يمكن تشغيل Toggle وظيفة في نفس الوقت ، لذلك هذا يمكن أن يحدث

    // thread 1 is running this code
    if(value == 0) 
    {
        value = 1; 
        // RIGHT NOW, thread 2 steps in.
        // It sees value as 1, so runs the other branch, and changes it to 0
        // This causes your method to return 0 even though you actually want 1
    }
    else if(value == 1) 
    { 
        value = 0; 
    }
    return value;

تحتاج إلى تشغيل التالية الافتراض.

إذا 2 المواضيع تشغيل, أنها يمكن تعشيق والتفاعل مع بعضنا البعض بشكل عشوائي في أي نقطة.يمكنك أن تكون في منتصف الطريق من خلال الكتابة أو القراءة 64 بت عدد صحيح أو تعويم (على 32 بت وحدة المعالجة المركزية) و آخر خيط يمكن أن تقفز في وتغييره من تحت لك.

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

يمكنك أن تقرر ماذا وأين قفل قبل التفكير في مثل هذه الأمور:

عن كتلة معينة من التعليمات البرمجية ، something تغير من تحت لي ، سيكون الأمر ؟ إذا كان من شأنه أن تحتاج إلى أن قفل something لمدة البرمجية حيث أنه يهم.

النظر في المثال الخاص بك مرة أخرى

    // we read value here
    if(value == 0) 
    {
        value = 1; 
    }
    else if(value == 1) 
    { 
        value = 0; 
    }
    // and we return it here
    return value;

من أجل العودة إلى ما كنا نتوقع أن نفترض أن value لن يتغير بين قراءة ، return.من أجل هذا الافتراض أن يكون في الواقع الصحيح ، تحتاج إلى قفل value لمدة من أن كتلة التعليمات البرمجية.

لذلك كنت تفعل هذا:

lock( value )
{
     if(value == 0) 
     ... // all your code here
     return value;
}

ومع ذلك

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

هذا هو ما بن Scheirman في اشارة الى.

نصائح أخرى

الأصلي impplementation ليس موضوع آمنة ، كما بن نقطة

طريقة بسيطة لجعل هذا الموضوع آمنة لإدخال قفل البيان.على سبيل المثال.مثل هذا:

public class MyClass
{
    private Object thisLock = new Object();
    private static readonly MyClass instance = new MyClass();
    public static MyClass Instance
    {
        get { return instance; }
    }
    private Int32 value = 0;
    public Int32 Toggle()
    {
        lock(thisLock)
        {
            if(value == 0) 
            {
                value = 1; 
            }
            else if(value == 1) 
            { 
                value = 0; 
            }
            return value;
        }
    }
}

هذا ما ظننت.ولكن أنا تبحث عن التفاصيل...'تبديل()' ليس أسلوب ثابت ، وإنما هو عضو خاصية ثابتة (عند باستخدام 'المثال').هل هذا ما يجعل فإنه مشترك بين المواضيع ؟

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

وكيف ينطبق هذا على وحدانية في العامة.يجب أن تعالج هذا في كل طريقة في صفي ؟

كما قلت أعلاه, لأن المفرد تعرف diferent موضوع رصا نفس الكائن, ربما في نفس الوقت.هذا لا يعني أن عليك أن تجعل كل طريقة الحصول على القفل.إذا لاحظت أن simultaneos الاحتجاج يمكن أن يؤدي إلى تلف الدولة من الدرجة ثم يجب تطبيق الطريقة التي ذكرتها @توماس

يمكن أن أفترض أن المفرد نمط يعرض لي وإلا جميل مؤشر الترابط-الآمن فئة كل موضوع المشاكل العادية ثابت الأعضاء ؟

لا.الفئة الخاصة بك هو ببساطة لا threadsafe.المفرد له علاقة معها.

(أنا على الحصول على رأسي حول حقيقة تلك الحالة ودعا أعضاء كائن ثابت يسبب خيوط المشاكل)

هو أن تفعل شيئا مع ذلك أيضا.

عليك أن تفكر مثل هذا:هل من الممكن في البرنامج لمدة 2 (أو أكثر) المواضيع للوصول إلى هذه القطعة من البيانات في نفس الوقت ؟

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

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

private static object _lockDummy = new object();


...

lock(_lockDummy)
{
   //do stuff
}

أريد أن أضيف أيضا محمية منشئ MyClass منع المترجم من توليد العامة منشئ افتراضي.

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

Bingo :-)

أحصل عليه الآن.إنه عالم قاس.كنت أتمنى لو لم تكن إعادة بيع ديون رمز تراث :(

للأسف خاصية تعدد صعب عليك أن تكون في غاية العظمة عن الأشياء :-) أبسط حل في هذه الحالة هو أن العصا مع المفرد ، إضافة قفل حول قيمة, كما في الأمثلة.

في الواقع أنا لا أعرف C#.... ماولكن أنا موافق على جافا لذا سوف تعطي الجواب على ذلك ، نأمل أن اثنين مماثلة بما فيه الكفاية أنه سوف يكون من المفيد.إذا لم تعتذر.

الجواب, لا, انها ليست آمنة.موضوع واحد يمكن أن نسميه تبديل() في نفس الوقت الآخر ، وأنه من الممكن ، على الرغم من أن هذا الرمز ، Thread1 يمكن تعيين value بين الأوقات التي Thread2 يتحقق ذلك عندما يحدد ذلك.

لإصلاح, ببساطة جعل تبديل() synchronized.وهو لا يمنع على أي شيء أو استدعاء أي شيء يمكن أن تفرخ موضوع آخر الذي يمكن أن نسميه تبديل(), لذلك كل ما عليك القيام به حفظه.

اقتباس:

if(value == 0) { value = 1; }
if(value == 1) { value = 0; }
return value;

value سوف تكون دائما 0...

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