سؤال

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

int m_foo;

void Read() // executed by thread X (on processor #0)
{
   Console.Write(m_foo);
}

void Write() // executed by thread Y (on processor #1)
{
   m_foo = 1;
}

هل هناك احتمال بعد اكتب() تم الانتهاء من التنفيذ، وينفذ بعض الخيط الآخر اقرأ() ولكن في الواقع سوف نرى "0" كما القيمة الحالية؟ (منذ ربما لم يتم مسح الكتابة السابقة إلى m_foo بعد؟).
أي نوع من البدائيات (بجانب الأقفال) المتاحة لضمان مسح الكتب؟


تعديل
في نموذج التعليمات البرمجية لقد استخدمت، يتم وضع الكتابة والقراءة بطريقة مختلفة. لا يخيف. يمثل memorybarrier يؤثر فقط على تعليم التعليمات الموجودة في نفس النطاق؟

أيضا، لنفترض أنه لن ينبذه JIT، كيف يمكنني التأكد من أن القيمة المكتوبة إلى m_foo لن يتم تخزينها في سجل، ولكن على الذاكرة الرئيسية؟ (أو عند قراءة M_FOO، فلن تحصل على قيمة قديمة من ذاكرة التخزين المؤقت لوحدة المعالجة المركزية).

هل من الممكن تحقيق ذلك دون استخدام الأقفال أو الكلمة الرئيسية "المتقلبة"؟ (أيضا، دعنا نقول أنني لا أستخدم أنواع بدائية، ولكن الهيكل بحجم كلمة حتى لا يمكن تطبيق متقلبة.)

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

المحلول

وقد ذكرت بالفعل متقلبة ومشتركة بالفعل، طلبت أن تكون بيئيتين، إضافة واحدة إلى القائمة هي استخدامها Thread.MemoryBarrier() قبل يكتب أو يقرأ. هذا الضمانات لا يتم إعادة ترتيب من الذاكرة يكتب ويقرأ.

هذا يفعل "باليد" ماذا lock, Interlocked و volatile يمكن أن تفعل تلقائيا معظم الوقت. يمكنك استخدام هذا بديل كامل لأي تقنية أخرى، لكنه يمكن القول أن يسافر أصعب طريق للسفر، وكذلك يقول MSDN:

"من الصعب بناء البرامج الصحيحة الصحيحة باستخدام memorybarrier. بالنسبة لمعظم الأغراض، يوفر بيان قفل C #، عبارة SynClock Visual Basic، وطرق فئة الشاشة أسهل وأقل طرق عرضة للخطأ لمزامنة الوصول إلى الذاكرة. نوصي أنك تستخدمها بدلا من memorybarrier. "

كيفية استخدام memorybarrier

مثال جيد للغاية هي تطبيقات VolatileRead و VolatileWrite, ، أن كل من الاستخدام داخليا MemoryBarrier. وبعد قاعدة الإبهام الأساسية للمتابعة هي: عند قراءة متغير، ضع حافز ذاكرة بعد القراءة. عند كتابة القيمة، يجب أن يأتي حاجز الذاكرة قبل الكتابة.

في حال كنت تشك في ما إذا كان هذا أقل كفاءة lock, بالنظر إلى أن القفل ليس أكثر من "المبارزة الكاملة"، في أنه يضع حاجز ذاكرة قبل وبعد كتلة التعليمات البرمجية (تجاهل الشاشة للحظة). هذا المبدأ موضح جيدا في هذا مقال نهائي ممتاز على مؤشرات الترابط وقفل وحواجز الذاكرة المتقلبة والذاكرة من قبل Albahari.

من العاكس:

public static void VolatileWrite(ref byte address, byte value)
{
    MemoryBarrier();
    address = value;
}

public static byte VolatileRead(ref byte address)
{
    byte num = address;
    MemoryBarrier();
    return num;
}

نصائح أخرى

إذا كنت ترغب في التأكد من كتابته على الفور وبمطل، ثم قم بتمييزه volatile, ، أو (مع المزيد من الألم) استخدام Thread.VolatileRead / Thread.VolatileWrite (ليس خيارا جذابا، وسهل تفويته، مما يجعله عديم الفائدة).

volatile int m_foo;

وإلا فإن لديك ضمانات تقريبا من أي شيء (بمجرد أن تتحدث مؤشرات الترابط متعددة).

قد ترغب أيضا في النظر في قفل (Monitor) أو Interlocked, ، والتي من شأنها أن تحقق نفس التأثير طالما ال نفس يستخدم النهج من جميع الوصول (أي الكل lock, ، أو الكل Interlocked, ، إلخ).

طالما أنك لا تستخدم أي مزامنة، فلن تضمن أن مؤشر ترابط يعمل على معالج واحد يرى التغييرات التي يقوم بها مؤشر ترابط آخر يعمل على معالج آخر. وذلك لأن القيمة يمكن تخزينها مؤقتا في مخطط CPU أو في سجل وحدة المعالجة المركزية.

لذلك تحتاج إلى تمييز المتغير كقليم. من شأنها أن تنشئ "يحدث - قبل الإبلاغ بين كتابة الكتب.

هذا ليس مشكلة ذاكرة التخزين المؤقت المعالج. عادة ما يتم تحويل الكتابة (يكتب الذهاب إلى ذاكرة التخزين المؤقت والذاكرة الرئيسية) وستكون جميع القراءات الوصول إلى ذاكرة التخزين المؤقت. ولكن هناك العديد من المخابئ الأخرى في الطريق (لغة البرمجة، المكتبات، نظام التشغيل، I / O. المخازن المؤقتة، إلخ). يمكن للمترجم أيضا اختيار إبقاء متغير في سجل المعالج وعدم الكتابة أبدا إلى الذاكرة الرئيسية (هذا ما تم تصميم المشغل المتقلب لتجنب تخزين القيمة في السجل عندما يمكن أن يكون الذاكرة المعينة I / O).

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

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

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