نقول عن جزء من الكود أنها Thread-Safe إذا بالإمكان تنفيذها من خلال أكثر من خط تنفيذ واحد في نفس الوقت.
ذلك الجزء من الكود يجب أن يحقق حاجة خطوط التنفيذ للوصول إلى المتحولات المشتركة من جهة, ومن جهة أخرى يجب أن يضمن أن الوصول (القراءة أو الكتابة) من وإلى تلك المتحولات المشتركة يتم من خلال خط تنفيذ واحد في اللحظة الزمنية الواحدة.
هناك العديد من الطرق لتحقيق الـ Thread Safety:
إعادة الدخول Re-Entrancy:
هي كتابة جزء الكود الذي يجب أن يكون Thread-Safe في تابع واحد فقط, بشرط أن تكون كافة المتحولات التي يستخدمها هذا التابع معرفة داخله فقط.
عندما ينفذ هذا التابع من خلال أكثر من خط تنفيذ فإن المتحولات التي يستخدمها سوف تخزن داخل المكدس المحلي للتابع المرتبط بخط التنفيذ بدل أن تخزن في متحولات عامة.
الإستبعاد المتبادل Mutual Exclusion:
هي إستخدام مكانيكة محددة تضمن أن يتم الوصول (القراءة أو الكتابة) من وإلى المتحولات العامة بشكل متسلسل (على الدور يعني).
في هذه الطريقة يوجد العديد من المشاكل التي يمكن أن تواجهنا عند تنفيذ هذه المكانيكية (deadlocks, livelocks, starvation)
إستخدام التخزين على مستوى خط التنفيذ Thread-Local storage:
بهذا الطريقة يمكننا تخزين البيانات العامة على مستوى خط التنفيذ, مما يعطينا وصولاً عاماً إلى تلك البيانات ولكن على مستوى خط التنفيذ وليس على مستوى التابع, وبما أن البيانات عامة على مستوى خط التنفيذ فإن حالة القراءة منها أو التعديل عليها بنفس الوقت غير موجودة, وحالة الوصول إلى نفس البيانات من خلال أكثر من خط تنفيذ أيضاً غير موجودة.
التعليمات الذرية Atomic Operation:
في هذه الحالة يجب أن نستخدم العمليات الذرية ـ التي لايمكن أن يتم مقاطعتها من قبل خطوط التنفيذ الأخرى عند عملها ـ لتعديل البيانات العامة, هذه الطريقة بحاجة إلى إستخدام تعليمات خاصة من لغة الآلة التي عادة ما تكون متاحة في لغات البرمجة عالية المستوى.بما إن هذه التعليمات لايمكن مقاطعتها أثناء التنفيذ فهذا يضمن أن تبقى البيانات العامة في الحالة الصحيحة بغض النظر عن عدد خطوط التنفيذ التي تصل إليها.
بنظرة عامة نجد أنا مجال الرؤية للمتحولات أو البيانات العامة هو الذي يلعب الدور الأهم في كون جزء الكود هو Thread-Safe أم لا, ونجد أيضاً أنه لدينا ثلاث مجالات للرؤية للمتحولات أو البيانات العامة التي نتعامل معها:
1- المتحولات العامة على مستوى كافة خطوط التنفيذ وهي الأخطر, لأنه يمكن الوصول إليها من خلال أي تابع يُنفذ من خلال أي خط تنفيذ, مما يعني صعوبة السيطرة على صحة القيمة الموجودة في تلك المتحولات.
2- المتحولات العامة على مستوى خط تنفيذ محدد, هذه المتحولات يمكن الوصول إليها من خلال أي تابع يتم تنفيذه على خط تنفيذ واحد وتكون قيمها مختلفة تمام من خط تنفيذ إلى خط تنفيذ آخر ولا يوجد أي ربط فيما بينها على مستوى كافة خطوط التنفيذ, وإنما يتم تخزينها في على مستوى المكدس لخط التنفيذ.
3- المتحولات المحلية للتابع الواحد هذه المتحولات تأخذ قيمها الخاصة مع كل إستدعاء لهذا التابع, مما يعني أن هذه القيم يتم تخزينها على مستوى المكدس المحلي للتابع مما يعني أن هذه القيم غير مرتبطة نهائياً بأي خط تنفيذ.
المصطلحات المستخدمة:
خط التنفيذ = Thread
البيانات العامة أو المتحولات العامة = Shared Resources
ذلك الجزء من الكود يجب أن يحقق حاجة خطوط التنفيذ للوصول إلى المتحولات المشتركة من جهة, ومن جهة أخرى يجب أن يضمن أن الوصول (القراءة أو الكتابة) من وإلى تلك المتحولات المشتركة يتم من خلال خط تنفيذ واحد في اللحظة الزمنية الواحدة.
هناك العديد من الطرق لتحقيق الـ Thread Safety:
إعادة الدخول Re-Entrancy:
هي كتابة جزء الكود الذي يجب أن يكون Thread-Safe في تابع واحد فقط, بشرط أن تكون كافة المتحولات التي يستخدمها هذا التابع معرفة داخله فقط.
عندما ينفذ هذا التابع من خلال أكثر من خط تنفيذ فإن المتحولات التي يستخدمها سوف تخزن داخل المكدس المحلي للتابع المرتبط بخط التنفيذ بدل أن تخزن في متحولات عامة.
الإستبعاد المتبادل Mutual Exclusion:
هي إستخدام مكانيكة محددة تضمن أن يتم الوصول (القراءة أو الكتابة) من وإلى المتحولات العامة بشكل متسلسل (على الدور يعني).
في هذه الطريقة يوجد العديد من المشاكل التي يمكن أن تواجهنا عند تنفيذ هذه المكانيكية (deadlocks, livelocks, starvation)
إستخدام التخزين على مستوى خط التنفيذ Thread-Local storage:
بهذا الطريقة يمكننا تخزين البيانات العامة على مستوى خط التنفيذ, مما يعطينا وصولاً عاماً إلى تلك البيانات ولكن على مستوى خط التنفيذ وليس على مستوى التابع, وبما أن البيانات عامة على مستوى خط التنفيذ فإن حالة القراءة منها أو التعديل عليها بنفس الوقت غير موجودة, وحالة الوصول إلى نفس البيانات من خلال أكثر من خط تنفيذ أيضاً غير موجودة.
التعليمات الذرية Atomic Operation:
في هذه الحالة يجب أن نستخدم العمليات الذرية ـ التي لايمكن أن يتم مقاطعتها من قبل خطوط التنفيذ الأخرى عند عملها ـ لتعديل البيانات العامة, هذه الطريقة بحاجة إلى إستخدام تعليمات خاصة من لغة الآلة التي عادة ما تكون متاحة في لغات البرمجة عالية المستوى.بما إن هذه التعليمات لايمكن مقاطعتها أثناء التنفيذ فهذا يضمن أن تبقى البيانات العامة في الحالة الصحيحة بغض النظر عن عدد خطوط التنفيذ التي تصل إليها.
بنظرة عامة نجد أنا مجال الرؤية للمتحولات أو البيانات العامة هو الذي يلعب الدور الأهم في كون جزء الكود هو Thread-Safe أم لا, ونجد أيضاً أنه لدينا ثلاث مجالات للرؤية للمتحولات أو البيانات العامة التي نتعامل معها:
1- المتحولات العامة على مستوى كافة خطوط التنفيذ وهي الأخطر, لأنه يمكن الوصول إليها من خلال أي تابع يُنفذ من خلال أي خط تنفيذ, مما يعني صعوبة السيطرة على صحة القيمة الموجودة في تلك المتحولات.
2- المتحولات العامة على مستوى خط تنفيذ محدد, هذه المتحولات يمكن الوصول إليها من خلال أي تابع يتم تنفيذه على خط تنفيذ واحد وتكون قيمها مختلفة تمام من خط تنفيذ إلى خط تنفيذ آخر ولا يوجد أي ربط فيما بينها على مستوى كافة خطوط التنفيذ, وإنما يتم تخزينها في على مستوى المكدس لخط التنفيذ.
3- المتحولات المحلية للتابع الواحد هذه المتحولات تأخذ قيمها الخاصة مع كل إستدعاء لهذا التابع, مما يعني أن هذه القيم يتم تخزينها على مستوى المكدس المحلي للتابع مما يعني أن هذه القيم غير مرتبطة نهائياً بأي خط تنفيذ.
المصطلحات المستخدمة:
خط التنفيذ = Thread
البيانات العامة أو المتحولات العامة = Shared Resources
ليست هناك تعليقات:
إرسال تعليق