الدافع
من الاتصال بنموذج البرمجة (العملية) متعدد الخيوط، وما تعلمته هو أوليات المزامنة المتعلقة بالإشارة (Semaphore). لا أعرف سبب عدم وجود أشياء مقابلة في .Net Framework. والأمر الفظيع هو أنني استخدمتها لتنفيذ الكثير من أكواد C++ التي تم اختبارها عبر الزمن، ومن أجل منع شهداء الثورة من تناول الدواء والنزيف عبثًا، كان عليّ أن أنجب واحدًا بنفسي.
ما هي الإشارة؟
إذا كنت تفهم بالفعل مفهوم الإشارة، يرجى تخطي هذا القسم.
Semaphore عبارة عن أداة تستخدم في بيئة متعددة الخيوط وهي مسؤولة عن تنسيق الخيوط المختلفة للتأكد من إمكانية استخدام الموارد العامة بشكل صحيح ومعقول.
دعونا نلقي نظرة على كيفية عمل موقف السيارات. من أجل التبسيط، افترض أن موقف السيارات به ثلاثة أماكن فقط لوقوف السيارات، وجميع أماكن وقوف السيارات الثلاثة فارغة في البداية. هذا إذا جاءت خمس سيارات في نفس الوقت، وسمح حارس البوابة لثلاث منها بالدخول دون عائق، ثم قام بوضع كتلة السيارة، فيجب على السيارات المتبقية الانتظار عند المدخل، وسيتعين على السيارات اللاحقة أيضًا الانتظار عند المدخل. مدخل. في هذا الوقت، غادرت سيارة موقف السيارات بعد أن علم حارس البوابة بذلك، فتح حاجز السيارة ووضع سيارة واحدة فيه. إذا تركت سيارتان أخريان، فيمكنه وضع سيارتين أخريين، وهكذا.
في نظام مواقف السيارات هذا، تعد أماكن وقوف السيارات من الموارد العامة، وكل سيارة تشبه الخيط، ويعمل حارس البوابة كإشارة.
علاوة على ذلك، فإن خصائص الإشارة هي كما يلي: الإشارة عبارة عن عدد صحيح غير سالب (عدد مواقف السيارات)، وجميع الخيوط (المركبات) التي تمر بها ستقلل العدد الصحيح بمقدار واحد (تمريره هو بالطبع استخدام الموارد ).عندما تكون قيمة العدد الصحيح عند الصفر، فإن جميع الخيوط التي تحاول تمريرها ستكون في حالة انتظار. نحدد عمليتين على الإشارة: الانتظار والإفراج. عندما يستدعي الخيط عملية الانتظار، فإنه إما يمرر ثم يقلل الإشارة بمقدار واحد، أو ينتظر حتى تصبح الإشارة أكبر من واحد أو تنتهي المهلة. ينفذ الإصدار بالفعل عملية إضافة على الإشارة، والتي تتوافق مع مغادرة السيارة لموقف السيارات. السبب وراء تسمية هذه العملية بـ "التحرير" هو أن عملية الإضافة تحرر فعليًا الموارد التي تحرسها الإشارة.
ينجز
كما نعلم جميعًا، تتضمن تسهيلات مزامنة سلسلة المحادثات المتوفرة في مكتبة فئة .Net Framework ما يلي:
Monitor وAutoResetEvent وManualResetEvent وMutex وReadWriteLock وInterLock. من بينها، AutoResetEvent وManualResetEvent وMutex مشتقة من WaitHandler، وهي في الواقع تقوم بتغليف كائنات kernel التي يوفرها نظام التشغيل. يجب أن يكون الآخرون أصليين في الجهاز الظاهري .Net. من الواضح أن المرافق من كائنات kernel لنظام التشغيل أقل كفاءة في الاستخدام. ومع ذلك، الكفاءة ليست مشكلة يجب أن نأخذها في الاعتبار هنا، وسوف نستخدم شاشتين وكائن ManualResetEvent لمحاكاة الإشارة.
الرمز هو كما يلي:
إشارة الطبقة العامة
{
Private ManualResetEvent waitEvent = new ManualResetEvent(false);
كائن خاص syncObjWait = كائن جديد ()؛
Private int maxCount = 1; // الحد الأقصى لعدد الموارد
Private int currentCount = 0; // العدد الحالي للموارد
public Semaphore()
{
}
الإشارة العامة (int maxCount)
{
this.maxCount = maxCount;
}
الانتظار المنطقي العام ()
{
lock( syncObjWait ) // يمكن لموضوع واحد فقط إدخال الكود التالي
{
bool waitResult = this.waitEvent.WaitOne(); // عدد الموارد المنتظرة هنا أكبر من الصفر
إذا (انتظر النتيجة)
{
قفل (هذا)
{
إذا (العدد الحالي > 0)
{
currentCount--;
إذا (العدد الحالي == 0)
{
this.waitEvent.Reset();
}
}
آخر
{
System.Diagnostics.Debug.Assert( false, "الإشارة لا تسمح بالعدد الحالي <0" );
}
}
}
عودة الانتظار النتيجة؛
}
}
/**//// <summary>
/// عملية الانتظار التي تسمح بعودة المهلة
/// </الملخص>
/// <param name="millithansTimeout"></param>
/// <returns></returns>
الانتظار المنطقي العام (int ميلي ثانيةTimeout)
{
lock( syncObjWait ) // يضمن جهاز المراقبة أن رمز فئة النطاق موجود داخل القسم الحرج
{
bool waitResult = this.waitEvent.WaitOne(millithansTimeout,false);
إذا (انتظر النتيجة)
{
قفل (هذا)
{
إذا (العدد الحالي > 0)
{
currentCount--;
إذا (العدد الحالي == 0)
{
this.waitEvent.Reset();
}
}
آخر
{
System.Diagnostics.Debug.Assert( false, "الإشارة لا تسمح بالعدد الحالي <0" );
}
}
}
عودة الانتظار النتيجة؛
}
}
إصدار المجمع العام ()
{
lock( this ) // يضمن جهاز المراقبة أن رمز فئة النطاق موجود داخل القسم الحرج
{
currentCount++;
إذا (currentCount> this.maxCount)
{
currentCount = this.maxCount;
عودة كاذبة.
}
this.waitEvent.Set(); // اسمح للخيط الذي يستدعي الانتظار بالدخول
}
عودة صحيحة؛
}
}