جارٍ تحميل الدرس...
في نافذة الطباعة اختر «حفظ كملف PDF» كوجهة.
معمل نظم التشغيل - الأسبوع السابع
C#إنشاء الخيوط، وتجنب حالات التسابق، واستخدام ThreadPool
code وdata، لكنها لا تنفذ بمفردها.Program Counter وStack ومجموعة سجلات خاصة به.البرنامج
ملف تنفيذي على القرص
العملية
نسخة قيد التنفيذ
الخيط
أصغر وحدة تنفيذ
new Thread(methodName) كائن خيط مرتبطا بالدالة التي سيشغلهاStart() التنفيذ على الخيط الجديدJoin() الخيط المستدعي حتى ينتهي الخيط الهدف، وهو نمط fork-join الكلاسيكيThread myThread = new Thread(PrintNumbers);
myThread.Start();
myThread.Join(); // wait for it to finishTask1
ينفذ حتى الاكتمال
Task2
يبدأ بعد اكتمال Task1
Thread1
يعمل بالتوازي
Thread2
يعمل بالتوازي
I/O أو المهام المستقلة، لأن العمل يتداخل بدلا من الاصطفافمثال عملي
IsBackground = true علامة على الخيوط بأنها خيوط خلفية قبل تشغيلهاThread pingThread = new Thread(Ping);
Thread pongThread = new Thread(Pong);
pingThread.IsBackground = true;
pongThread.IsBackground = true;
pingThread.Start();
pongThread.Start();
pingThread.Join();
pongThread.Join();Unstarted
Start()Running
WaitSleepJoin
Stopped
Abort() أصبحت مهجورة ولا ينبغي استخدامها؛ ولا يمكن تشغيل خيط أكثر من مرةT1 و T2 يقرآن counter = 0
كل خيط يزيده محليا إلى 1
كل خيط يكتب 1
القيمة النهائية 1
المتوقع كان 2
مثال عملي
ThreadPool دون حماية العداد المشترك0، لأن الزيادات والنقصانات تلغي بعضهاstatic void IncrementCounter(object state)
{
// WITHOUT LOCK - race condition can occur
for (int i = 0; i < 100; i++) counter++;
}locklockT1: يطلب القفل
T1: ينفذ القسم الحرج
T2 ينتظر
T1: يحرر القفل
T2: يحصل على القفل وينفذ
static object lockObject = new object();
lock (lockObject)
{
for (int i = 0; i < 100; i++) counter++;
}ThreadPool)ThreadPoolThreadPool
Thread 1
Thread 2
Thread N
ThreadPool.QueueUserWorkItem(method) عملا ليشغل بخيط متاح من المجمعThreadPool.SetMaxThreads(50, 50) سقف عدد الخيوط العاملة المتزامنةThreadPool.SetMaxThreads(50, 50);
ThreadPool.QueueUserWorkItem(IncrementCounter);ThreadPool مقابل الخيوط اليدوية| الميزة | ThreadPool | الخيوط اليدوية |
|---|---|---|
| عبء الإنشاء | منخفض (إعادة استخدام) | مرتفع (إنشاء جديد) |
| التحكم | محدود | كامل |
| الأنسب لـ | المهام القصيرة | العمليات طويلة الأمد |
| التنظيف | تلقائي | يدوي |
long partialSum = 0;
for (int i = start; i <= end; i++) partialSum += i;
lock (lockObject) { totalSum += partialSum; }| الأسلوب | الزمن | معدل التسريع |
|---|---|---|
| خيط واحد | 4000 ms | 1x |
| أربعة خيوط | 1200 ms | 3.3x |
4x كاملا، بسبب العبء والمزامنةThreadPool للمهام القصيرةtry-catchAbort()Start() خيطا؛ وتحجب Join() حتى ينتهي، منفذة نمط fork-joinlock القسم الحرجThreadPool استخدام الخيوط العاملة للمهام القصيرة، وهو عموما أكفأ من إنشاء الخيوط يدوياMahmoud Abas|معمل نظام التشغيل - الأسبوع 7