الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

أساسيات ال Threading مشكلة Race Condition

بدأه admin_cs في 14 أكتوبر 2008 · 5 رد · 4,045 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

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

المهم كانت تلك المقدمة لتحفذنا على مراعاه الجديد فى عالم البرمجة والكمبيوتر ...ومن هذا الجديد القديم أيضا ومعروف ألا وهى البرمجة المتوازية Parallel programming

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

معذرة على الاطالة لكن كانت لابد للدخول فى صلب الموضوع ألا وهو مشكلة Race Conditionولمن لايعرف هذه المشكلة فهى ببساطة تسابق متزامن لعمليتين كلاهما يؤدى نفس الغرض ..احدهما قد يأتى قبل الاخر اعتمادا على حدث Event معين او تزامن ما ..وهى عشوائية بحتة ...(نظريا هى تشبه مشكلة الـ DeadLock) ..لكن ما الذى يعنينى كمبرمج من هذا الصداع ؟؟!! ....الاجابة فتش عنها فى الاعلى اذا كنت مهتم لما قلت ..لكن دع الكود يتكلم عنى ...مستعملا VS2008 واطار الدوت نت 3.5 ..مع ملاحظة الترقية التالية للـParallel Extention .وإلا فالعمل على .NET 2.0 قد تضطر لعملSnippest للكلاس Parallel الى جانب التعامل مع الـDelegate بالطريقة المعتادة !

class RaceCondition
	{  
	 public static int Total = 0;  

	public void Test(string myString)	
   {  

	  // Do something with myString:  
	   Total++;   : 
	}
   }  }

الكود واضح عبارة عن كلاس به دالة سنقوم بمناداتها لحساب عدد مرات تكرار النص Total فيها عن طريق عدد من الـThreads فى الكود التالى ...>

// بالطيع تنبه اسفل الى الـ Lambda Expression

int LoopsNo = 200000; 
int MultNo=4;
var test =new RaceCondition() //تنبه للـvar ممكن استعمال الكلاس Test لكن فقط هنا انا ابرز الجديد فى .NET 3.5 
Parallel.For(0, MultNo, (taskNo) => 
{
 for (int i = 0; i < LoopsNo; i++)
{
RaceCondition.test("Message " + i.ToString());
}
});
Console.WriteLine("{0} Expected", LoopsNo* MultNo);
Console.WriteLine("{0} Actual", RaceCondition.Total);

طبعا ناد على الدالة سواءا من داخل الكلاس او بكلاس منفصل لا يهم ..ركز فى الآت ....بالطبع أحدهم يصرخ ماهذه التفاهة هل كل هذا من أجل حساب 4*200000 ؟!!

طبعا :) ....لااااا :wink: ..النتيجة المتوقعة هى 800000 اليس كذلك ؟؟ ....خطأ ...النتيجة لن تظهر كذلك إلا مصادفة ..اذا ما الاجابة الصحيحة ؟؟ الاجابة الصحيحة غير معروفة ومتغيرة دائما على حسب الـtiming او اى حدث Event آخر غير معلوم ...فمثلا النتيجة اول ماظهرت ظهرت كالتالى :

800000 Expected

736354 Actual

وهكذا كلما اعدت تشغيل البرنامج سيظهر نتيجة مختلفة تماما .........بالطبع لا تلعن المترجم الخاص بالدوت نت او تلعن ميكروسوفت ..الكود صحيح والمترجم صحيح ..اذا ماذا حدث؟؟!!.... السر يكمن فى المعالجة متعددة الخيوط MultiThreading ، لمن لم يتعود على هذا النوع ، وبالطبع أخذ فى اعتباره عندما قام هو بتحليل الكود ان العبارة Total++ ماهى الا مجرد سطر برمجى واحد ينفذ مرة واحدة ...هذا للمبرمج الطبيعى الكود ماهو الا single thread process ......لكن فى الحقيقة الذى حدث هو ان تمت معالجتها على انها اربع تعليمات وليس تعليمة برمجية واحدة !!!! ..الم اقل لك ان المعالجة متعددة الخيوط مربكة للدماغ ؟؟!! :mrgreen: وحتى تصدقنى ..قم بعمل ترجمة عكسية لهذه العبارة فقط (كالمعتاد) الى IL لتشاهد معى هذا

L_0001: ldsfld int32 CSharpx.RaceCondition::Total  
L_0006: ldc.i4.1
L_0007: add 
L_0008: stsfld int32 CSharpx.RaceCondition::Total

وهو ما معناه الاتى :

1-احسب القيمة الحالية للمتغير Total

2-حصل المترجم على القيمة 1 //تذكر ++ تعنى زيادة بمقدار واحد

3-اجمع القيمتين السابقتين Total +1 //بالنسبة للمرة الواحدة وبالطبع قيمة Total تتغير

4-خزن الناتج فى المتغير Total

هذا بالطبع بالنسبة للمعالجة التقليدية ،لكن ماذا لو تم معالجتها على اعتبار انها عمليتين 2 threads ??!! هل ياترى ستبقى النتيجة كما هى ؟؟!! لنر .....>

[Thread 1] 1. Get the current value of Total (gets 2)

[Thread 1] 2. Get the value 1

[Thread 2] 1. Get the current value of Total (gets 2)

[Thread 2] 2. Get the value 1

[Thread 1] 3. Add the two numbers together (2 + 1)

[Thread 1] 4. Save the result back into Total (saves 3)

[Thread 2] 3. Add the two numbers together (2 + 1)

[Thread 2] 4. Save the result back into Total(saves 3)

بالطبع سنتفترض ان قيمة الـTotal حاليا =2 ..وذلك لحجز القيمتين لزوج العمليات 2 threads ...

وأخيرا بعد صداع الراس المؤلم سيتضح العيب الذى ندندن حوله من الصبح :!: ...هل لاحظت ان قيمة Total لم تزداد إلا بمقدار 1 ؟؟!! تذكر ان كلا القيمتين الحاليتين من زوج العميات الخيطية =2 ...والعبارة البرمجية ++ تزيد بمقدار 1 لكلاهما فى ذات الوقت (هل تذكر اول المقالة التسارع لإنجاز نفس المهمة ..أرجو ذلك لأنى زودتها حبتين :) )وبالتالى كانت المحصلة النهائية هى زيادة واحدة بمقدار واحد وهو مشكلتنا المسماه بالـRace Condition وهى ما تسببت فى ظهور قيم متغيرة كل مرة على حسب سرعة المعالجة او اى عوامل خارجية من نظام التشغيل الى العملية المشتركة معك فى نفس المعالجة ............الخ .

طبعا هذه المشكلة على امل ان تحل . وإلا فما الجدوى من المعالجة متعددة الخيوط اذا كانت النتائج على غير المتوقع ؟؟!!

.وعلى حسب ما اطلعت عليه قريبا ان الاصدار .NET 4.0 أصلا موجه للمعالجة المتعددة الخيوط او المتزامنة عموما ..وهناك لغة تسمى Parallel C# تحت التطوير تبحث فى هذا المجال ....

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

فى امان الله[/

تم تعديل هذه المشاركة بواسطة admin_cs في 14 أكتوبر 2008 في 19:35

#2

المشكلة باختصار وجود global variables و يتم الوصول اليها من اكثر من thread

و من المحتمل قرأة المتغير في اكثر من thread في نفس اللحظة و يقوم كل منهم بالتعديل عليه

مثلا لو ان total الان يساوي 1 و تم قراته من 2 thread كانه يساوي 1 فبعد تنفيذ الزيادة ب 1 في كل thread يكون الناتج 2 و ليس 3

لان ال thread الذي يقوم بتعديل total في النهاية سوف يكتب علي تعديل ال thread الاول

و المشكله هي كيفية عمل concurrency لل shared state

و الحل لهذه المشكله Synchronization

بمعني عمل lock للمتغير لحساب thread واحد حتي ينتهي من التعديل فيسمح لغيره بعد ذلك قراة المتغير و تعديله يعني بالبلدي واحد واحد

و يكون الكود في ابسط اشكاله بالشكل التالي

   public void Test(string myString)	
   {  

	  // Do something with myString:  
				  //lock keyword implements Synchronization
				lock(this)
				{
				  Total++;  
				}
}

و من هنا ممكن ظهور مشكلة ال Deadlock بمعني thread A ينتظر thread B في جملة معينة و thread B ينتظر thread C في جملة معينة و Thread C ينتظر Thread A في جملة معينة

كلهم بينتظروا بعض يعني دائرة ليس لها نهاية deadlock (فقط هذا التبسيط للتوضيح)

تم تعديل هذه المشاركة بواسطة AhmedElbaz في 15 أكتوبر 2008 في 13:20

#3

أخى احمد الباز احسن الله اليك ..نعم ماتقول صحيح :thumb_up: ..وللأسف معروف أن الـ soft lock لايتحكم فيه بسهوله ...وهو على ما أعتقد سبب إتجاههم إلى تطوير اطار العمل .NET 4.0 .....وبالمناسبة وعلى الهامش ..موضوعك فى قسم المقالات عن VS2010 هو السبب فى طرحى للموضوع B)

#5

Nice article.. Parallel C# is just a new extension for C# and also for C++ to allow programmers in C# to write parallel applications easily.. The most powerfull tool now, yet not programmer friendly, that allows you to program on a wide scale (like super computers) is MPI.. The basics of all parallel libraries is to give you methods for reductions (Parallel.Reduce) and expansions (Parallel.For).

If you are using lock, don't lock on the (this), because you never know if the caller locks on your object, which would result in dead locks (two resources holding on the same lock).. If you want to use lock, lock on a private member.

private object lockObject = new Object();

lock (lockObject) {

}

Coding on the Cloud and for the Cloud!

My Blog

#6
اقتباس
...(نظريا هى تشبه مشكلة الـ DeadLock

عفوا الRace condition

هو محاولة اكثر من process للوصول الى ذاكرة مشتركة

DeadLock هو توقف اكثر من process بسبب ان كلا منهم يحجز موردا ولايستطيع اكمال عمله الا بالحصول على موارد محجوز بدوره من قبل الآخر

أضاعوني وأي فتى أضاعـوا * * * ليـوم كــريهـة وســـداد ثغــــر

وخـــــلونـي ومعتـرك المنايـا * * * وقد شـــرعوا أسنــتهم لنحـري

كأني لم أكــــــن فيهـم وسيطـا * * * ولم تك نســبتي في آل عمــرو

أجرر في الجـــوامع كـل يـوم * * * ألا لله مظــــلمتـي وهـصـــري

عسى الملك المجيب لمن دعاه * * * سينجيني فيعلم كيــف شكـري

فأجـــزي بالكرامـة أهـل ودي * * * وأجزي بالضـغينة أهل ضري

منتديات الرياضيات العربية

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…