قابلية الخطية

في البرمجة المتزامنة ، تكون العملية (أو مجموعة العمليات) قابلة للتسلسل الخطي إذا كانت تتكون من قائمة مرتبة من أحداث الاستدعاء والاستجابة ، والتي يمكن توسيعها بإضافة أحداث استجابة بحيث:
- يمكن إعادة التعبير عن القائمة الموسعة كتاريخ تسلسلي ( قابلة للتسلسل ).
- هذا التاريخ التسلسلي هو جزء من القائمة الأصلية غير الموسعة.
بشكل غير رسمي، هذا يعني أن قائمة الأحداث غير المعدلة قابلة للتسلسل إذا وفقط إذا كانت استدعاءاتها قابلة للتسلسل، ولكن بعض استجابات الجدول الزمني التسلسلي لم تُرجع بعد. [ 1 ]
في النظام المتزامن، يمكن للعمليات الوصول إلى كائن مشترك في الوقت نفسه. ولأن عدة عمليات تصل إلى كائن واحد، فقد تنشأ حالةٌ تقوم فيها عمليةٌ أخرى بتغيير محتويات الكائن أثناء وصول إحدى العمليات إليه. يُعدّ جعل النظام قابلاً للتسلسل الخطي أحد حلول هذه المشكلة. ففي النظام القابل للتسلسل الخطي، ورغم تداخل العمليات على الكائن المشترك، تبدو كل عملية وكأنها تحدث بشكل فوري. التسلسل الخطي شرطٌ أساسيٌّ لصحة النظام، إذ يُقيّد المخرجات الممكنة عند وصول عدة عمليات إلى كائن ما في وقت واحد. وهو خاصية أمان تضمن عدم اكتمال العمليات بشكل غير متوقع أو غير قابل للتنبؤ. إذا كان النظام قابلاً للتسلسل الخطي، فإنه يسمح للمبرمج بفهم النظام وتحليله. [ 2 ]
تاريخ
تم تقديم قابلية الخطية لأول مرة كنموذج اتساق بواسطة هيرليهي ووينغ في عام 1987. وقد شملت تعريفات أكثر تقييدًا للذرية، مثل "العملية الذرية هي التي لا يمكن مقاطعتها (أو لا يتم مقاطعتها) بواسطة عمليات متزامنة"، والتي عادة ما تكون غامضة بشأن متى تعتبر العملية بداية ونهاية.
يمكن فهم الكائن الذري بشكل مباشر وكامل من خلال تعريفه التسلسلي، كمجموعة من العمليات التي تُنفذ بالتوازي وتظهر دائمًا متتابعة؛ فلا مجال للتناقضات. وعلى وجه التحديد، تضمن قابلية الترتيب الخطي أن تُلاحظ جميع العمليات ثوابت النظام وتحافظ عليها : فإذا حافظت كل عملية على حدة على ثابت ما، فإن النظام ككل سيحافظ عليه.
تعريف
يتألف النظام المتزامن من مجموعة من العمليات التي تتواصل عبر هياكل بيانات أو كائنات مشتركة. وتُعدّ قابلية الترتيب الخطي مهمة في هذه الأنظمة المتزامنة، حيث يمكن الوصول إلى الكائنات من قِبل عمليات متعددة في الوقت نفسه، ويحتاج المبرمج إلى القدرة على استنتاج النتائج المتوقعة. وينتج عن تنفيذ النظام المتزامن سجلٌّ تاريخي ، وهو عبارة عن تسلسل مُرتب للعمليات المنجزة.
السجل هو سلسلة من الاستدعاءات والاستجابات التي تُجريها مجموعة من الخيوط أو العمليات على كائن ما. يُمكن اعتبار الاستدعاء بدايةً لعملية ما، والاستجابة نهايةً مُعلنةً لتلك العملية. لكل استدعاء لدالة ما استجابة لاحقة. يُمكن استخدام هذا لنمذجة أي استخدام لكائن ما. لنفترض، على سبيل المثال، أن خيطين، A وB، يحاولان الحصول على قفل، ويتراجعان إذا كان القفل محجوزًا بالفعل. يُمكن نمذجة ذلك على أنه استدعاء كلا الخيطين لعملية القفل، ثم تلقي كلا الخيطين استجابة، أحدهما ناجحة والآخر فاشلة.
| يستدعي القفل | B يستدعي القفل | تلقى A ردًا "فاشلًا" | حصل B على رد "ناجح" |
التاريخ التسلسلي هو تاريخٌ تُستجاب فيه جميع الاستدعاءات فورًا؛ أي أن الاستدعاء والاستجابة يُعتبران متزامنين. من المفترض أن يكون فهم التاريخ التسلسلي أمرًا بسيطًا، إذ لا يتضمن تزامنًا حقيقيًا؛ أما المثال السابق فلم يكن تسلسليًا، وبالتالي يصعب فهمه. وهنا تبرز أهمية الترتيب الخطي.
يمكن ترتيب التاريخ بشكل خطي إذا كان هناك ترتيب خطيمن العمليات المكتملة بحيث:
- لكل عملية مكتملة في، تُعيد العملية نفس النتيجة في التنفيذ كما لو تم إكمال كل عملية واحدة تلو الأخرى بالترتيب.
- إذا اكتملت العملية op 1 (حصلت على استجابة) قبل أن تبدأ العملية op 2 (يتم استدعاؤها)، فإن op 1 تسبق op 2 في[ 1 ]
بعبارة أخرى:
- يمكن إعادة ترتيب استدعاءاتها واستجاباتها للحصول على تاريخ متسلسل؛
- أن التاريخ التسلسلي صحيح وفقًا للتعريف التسلسلي للكائن؛
- إذا سبقت الاستجابة استدعاءً في التاريخ الأصلي، فيجب أن تسبقه في إعادة الترتيب التسلسلي.
لاحظ أن النقطتين الأوليين هنا تتوافقان مع قابلية التسلسل : يبدو أن العمليات تحدث بترتيب معين. أما النقطة الأخيرة فهي فريدة من نوعها في قابلية الخطية، وبالتالي فهي المساهمة الرئيسية لهيرليهي ووينغ. [ 1 ]
ضع في اعتبارك طريقتين لإعادة ترتيب مثال القفل أعلاه.
| يستدعي القفل | تلقى A ردًا "فاشلًا" | B يستدعي القفل | حصل B على رد "ناجح" |
إعادة ترتيب استدعاء B بعد استجابة A يُنتج سجلاً تسلسلياً. وهذا أمرٌ سهل التفسير، إذ تتم جميع العمليات الآن بترتيبٍ واضح. مع ذلك، لا يتوافق هذا مع التعريف التسلسلي للكائن (لا يتوافق مع دلالات البرنامج): كان من المفترض أن يحصل A على القفل بنجاح، ثم يُفترض أن يُنهي B العملية.
| B يستدعي القفل | حصل B على رد "ناجح" | يستدعي القفل | تلقى A ردًا "فاشلًا" |
هذا سجل تاريخي تسلسلي صحيح آخر. وهو أيضًا تسلسل خطي لأنه يطابق التعريف التسلسلي. تجدر الإشارة إلى أن تعريف التسلسل الخطي يمنع فقط إعادة ترتيب الاستجابات التي تسبق الاستدعاءات؛ وبما أن السجل الأصلي لم يتضمن أي استجابات قبل الاستدعاءات، فإنه يمكن إعادة ترتيبها. وبالتالي، فإن السجل الأصلي قابل للتسلسل الخطي بالفعل.
يمكن ترتيب الكائن (على عكس تاريخه) ترتيباً خطياً إذا أمكن ترتيب جميع سجلات استخدامه الصحيحة ترتيباً خطياً. وهذا ادعاء يصعب إثباته.
قابلية التخطيط الخطي مقابل قابلية التسلسل
لننظر إلى التاريخ التالي، مرة أخرى، لجسمين يتفاعلان مع قفل:
| يستدعي القفل | تم القفل بنجاح | يقوم B بتفعيل فتح القفل | تم فتح B بنجاح | يستدعي A فتح القفل | تم فتح القفل بنجاح |
هذا السجل غير صحيح لوجود نقطة يكون فيها كل من A وB مقفلين؛ علاوة على ذلك، لا يمكن إعادة ترتيبه إلى سجل تسلسلي صحيح دون انتهاك قاعدة الترتيب. لذلك، فهو غير قابل للتسلسل الخطي. مع ذلك، في ظل قابلية التسلسل، يمكن نقل عملية فتح القفل الخاصة بـ B إلى ما قبل القفل الأصلي لـ A، وهو سجل صحيح (بافتراض أن الكائن يبدأ السجل في حالة قفل).
| يقوم B بتفعيل فتح القفل | تم فتح B بنجاح | يستدعي القفل | تم القفل بنجاح | يستدعي A فتح القفل | تم فتح القفل بنجاح |
يُعد هذا الترتيب منطقيًا بشرط عدم وجود وسيلة بديلة للتواصل بين A و B. وتكون قابلية الترتيب الخطي أفضل عند النظر إلى الكائنات الفردية بشكل منفصل، حيث تضمن قيود إعادة الترتيب أن الكائنات المتعددة القابلة للترتيب الخطي، عند النظر إليها ككل، لا تزال قابلة للترتيب الخطي.
نقاط التخطيط الخطي
هذا التعريف للخطية يعادل ما يلي:
- جميع استدعاءات الدوال لها نقطة خطية في لحظة ما بين استدعائها واستجابتها.
- يبدو أن جميع الوظائف تحدث على الفور عند نقطة التخطيط الخطي الخاصة بها، وتتصرف كما هو محدد في التعريف التسلسلي.
عادةً ما يكون هذا البديل أسهل بكثير في الإثبات. كما أنه أسهل بكثير في الفهم بالنسبة للمستخدم، ويعود ذلك إلى حد كبير إلى بديهيته. هذه الخاصية المتمثلة في الحدوث الفوري، أو غير القابل للتجزئة، تؤدي إلى استخدام مصطلح " ذري " كبديل للمصطلح الأطول "قابل للخطية". [ 1 ]
في الأمثلة أدناه، تُعتبر نقطة التخطيط الخطي للعداد المبني على عملية المقارنة والتبديل هي نقطة التخطيط الخطي لأول (والوحيد) تحديث ناجح لعملية المقارنة والتبديل. أما العداد المبني باستخدام التأمين، فيمكن اعتباره خطيًا في أي لحظة طالما أن التأمينات سارية، حيث تُستبعد أي عمليات قد تتعارض معه من التنفيذ خلال تلك الفترة.
التعليمات الذرية الأولية
تحتوي المعالجات على تعليمات يمكن استخدامها لتنفيذ خوارزميات التأمين والخوارزميات التي لا تتطلب تأمينًا أو انتظارًا . كما أن القدرة على منع المقاطعات مؤقتًا، لضمان عدم إمكانية تبديل سياق العملية الجارية ، كافية أيضًا في المعالج الأحادي . تُستخدم هذه التعليمات مباشرةً من قِبل مُطوّري المُترجمات وأنظمة التشغيل ، ولكنها تُجرّد أيضًا وتُعرض كرموز بايت ووظائف مكتبية في لغات البرمجة عالية المستوى.
- القراءة والكتابة الذرية؛
- التبديل الذري (تعليمات RDLK في بعض أجهزة Burroughs الرئيسية ، وتعليمات XCHG x86 )؛
- اختبار وتعيين ؛
- جلب وإضافة ؛
- قارن وبدّل ؛
- load-link/store-conditional .
تتضمن معظم المعالجات عمليات تخزين غير ذرية فيما يتعلق بالذاكرة، مثل تخزين عدة كلمات وعمليات السلاسل النصية. في حال حدوث مقاطعة ذات أولوية عالية عند اكتمال جزء من عملية التخزين، يجب إكمال العملية عند عودة مستوى المقاطعة. يجب ألا يُعدّل الروتين الذي يعالج المقاطعة الذاكرة التي يتم تغييرها. من المهم مراعاة ذلك عند كتابة روتينات المقاطعة.
عند وجود تعليمات متعددة يجب إكمالها دون انقطاع، تُستخدم تعليمة من وحدة المعالجة المركزية لتعطيل المقاطعات مؤقتًا. يجب أن يقتصر هذا على عدد قليل من التعليمات، ويجب إعادة تفعيل المقاطعات لتجنب زمن استجابة غير مقبول للمقاطعات أو حتى فقدانها. هذه الآلية غير كافية في بيئة متعددة المعالجات، حيث يمكن لكل وحدة معالجة مركزية التدخل في العملية بغض النظر عن حدوث المقاطعات من عدمه. علاوة على ذلك، في وجود خط أنابيب التعليمات ، تُشكل العمليات غير القابلة للمقاطعة خطرًا أمنيًا، إذ يُمكن ربطها في حلقة لا نهائية لشن هجوم حجب الخدمة ، كما في ثغرة غيبوبة Cyrix .
يُتيح معيار لغة C و SUSv3sig_atomic_t عمليات قراءة وكتابة ذرية بسيطة؛ إلا أن زيادة أو إنقاص القيمة ليس مضمونًا أن يكون ذريًا. [ 3 ] تتوفر عمليات ذرية أكثر تعقيدًا في C11 ، والتي تُوفر stdatomic.h. تستخدم المُترجمات ميزات الأجهزة أو طرقًا أكثر تعقيدًا لتنفيذ هذه العمليات؛ ومن الأمثلة على ذلك مكتبة libatomic في GCC.
توفر مجموعة تعليمات ARMLDREX تعليماتٍ STREXيمكن استخدامها لتنفيذ الوصول الذري إلى الذاكرة باستخدام مراقبات حصرية مُطبقة في المعالج لتتبع عمليات الوصول إلى الذاكرة لعنوان مُحدد. [ 4 ] مع ذلك، إذا حدث تبديل سياق بين استدعاءات هذه التعليمات LDREX، STREXتشير الوثائق إلى أن التعليمات STREXستفشل، مما يستدعي إعادة محاولة العملية. في حالة بنية ARMv8-A ذات 64 بت، توفر هذه المجموعة LDXRتعليماتٍ STXRلأحجام البايت، ونصف الكلمة، والكلمة، والكلمة المزدوجة. [ 5 ]
العمليات الذرية عالية المستوى
أسهل طريقة لتحقيق الترتيب الخطي هي تشغيل مجموعات من العمليات الأساسية في قسم حرج . من الناحية النظرية، يمكن السماح للعمليات المستقلة بالتداخل مع أقسامها الحرجة بحذر، شريطة ألا يُخلّ ذلك بالترتيب الخطي. يجب أن يوازن هذا النهج بين تكلفة العدد الكبير من الأقفال وفوائد زيادة التوازي.
ثمة نهج آخر، يفضله الباحثون (لكنه لم يُستخدم على نطاق واسع في صناعة البرمجيات بعد)، وهو تصميم كائن قابل للتسلسل الخطي باستخدام العناصر الأولية الأصلية التي توفرها الأجهزة. يُمكن لهذا النهج أن يزيد من التوازي المتاح ويقلل من تكاليف التزامن، ولكنه يتطلب براهين رياضية تُثبت أن الكائنات تعمل بشكل صحيح.
يُعدّ توفير تجريد للذاكرة المعاملاتية حلاً واعداً يجمع بين هذين الأسلوبين . وكما هو الحال مع الأقسام الحرجة، يُحدّد المستخدم التعليمات البرمجية المتسلسلة التي يجب تشغيلها بمعزل عن الخيوط الأخرى. ثم يضمن التنفيذ تنفيذ التعليمات البرمجية بشكل ذري. يُعدّ هذا النمط من التجريد شائعاً عند التعامل مع قواعد البيانات؛ فعلى سبيل المثال، عند استخدام إطار عمل Spring ، يضمن وضع تعليق توضيحي @Transactional على دالة ما حدوث جميع تفاعلات قاعدة البيانات المُضمّنة في معاملة قاعدة بيانات واحدة . وتتجاوز الذاكرة المعاملاتية ذلك، إذ تضمن حدوث جميع تفاعلات الذاكرة بشكل ذري. وكما هو الحال مع معاملات قاعدة البيانات، تظهر مشكلات تتعلق بتكوين المعاملات، لا سيما معاملات قاعدة البيانات ومعاملات الذاكرة.
من السمات الشائعة عند تصميم الكائنات الخطية توفير واجهة "الكل أو لا شيء": إما أن تنجح العملية تمامًا، أو تفشل ولا تُحدث أي تغيير. ( تُشير قواعد بيانات ACID إلى هذا المبدأ باسم الذرية ). إذا فشلت العملية (عادةً بسبب عمليات متزامنة)، يجب على المستخدم إعادة المحاولة، وعادةً ما يُنفذ عملية مختلفة. على سبيل المثال:
- تقوم عملية المقارنة والتبديل بكتابة قيمة جديدة في موقع ما فقط إذا تطابقت محتويات الموقع مع قيمة قديمة مُدخلة. يُستخدم هذا الأسلوب عادةً في تسلسل القراءة والتعديل والمقارنة والتبديل: يقرأ المستخدم الموقع، ويحسب قيمة جديدة للكتابة، ثم يكتبها باستخدام المقارنة والتبديل؛ إذا تغيرت القيمة في الوقت نفسه، ستفشل عملية المقارنة والتبديل، وسيحاول المستخدم مرة أخرى.
- يقوم Load-link/store-conditional بتشفير هذا النمط بشكل مباشر: يقرأ المستخدم الموقع باستخدام load-link، ويحسب قيمة جديدة للكتابة، ويكتبها باستخدام store-conditional؛ إذا تغيرت القيمة في نفس الوقت، فسيفشل SC (store-conditional) وسيحاول المستخدم مرة أخرى.
- في معاملة قاعدة البيانات ، إذا تعذر إكمال المعاملة بسبب عملية متزامنة (على سبيل المثال في حالة تعطل )، فسيتم إجهاض المعاملة ويجب على المستخدم المحاولة مرة أخرى.
أمثلة
عدادات
ولإثبات قوة وضرورة قابلية الترتيب الخطي، سننظر في عداد بسيط يمكن للعمليات المختلفة زيادته.
نرغب في إنشاء كائن عداد يمكن لعدة عمليات الوصول إليه. تستخدم العديد من الأنظمة الشائعة العدادات لتتبع عدد مرات حدوث حدث معين.
يمكن الوصول إلى كائن العداد بواسطة عمليات متعددة، وله عمليتان متاحتان.
- زيادة - تضيف 1 إلى القيمة المخزنة في العداد، مع إرجاع إشعار تأكيد.
- القراءة - تُعيد القيمة الحالية المخزنة في العداد دون تغييرها.
سنحاول تنفيذ كائن العداد هذا باستخدام السجلات المشتركة .
محاولتنا الأولى التي سنرى أنها غير قابلة للتحويل إلى خطية لها التنفيذ التالي باستخدام سجل مشترك واحد بين العمليات.
غير ذري
التنفيذ البسيط وغير الذري:
زيادة:
- اقرأ القيمة في السجل R
- أضف واحدًا إلى القيمة
- يكتب القيمة الجديدة مرة أخرى في السجل R
يقرأ:
اقرأ السجل R
هذا التنفيذ البسيط غير قابل للتحويل إلى خطي، كما يتضح من المثال التالي.
تخيل أن عمليتين تعملان على الوصول إلى كائن العداد الوحيد الذي تمت تهيئته بقيمة 0:
- تقوم العملية الأولى بقراءة القيمة في السجل على أنها 0.
- تضيف العملية الأولى واحدًا إلى القيمة، ويجب أن تكون قيمة العداد 1، ولكن قبل أن تنتهي من كتابة القيمة الجديدة مرة أخرى إلى السجل، قد يتم تعليقها، وفي هذه الأثناء تعمل العملية الثانية:
- تقوم العملية الثانية بقراءة القيمة الموجودة في السجل، والتي لا تزال تساوي 0؛
- تضيف العملية الثانية واحدًا إلى القيمة؛
- تقوم العملية الثانية بكتابة القيمة الجديدة في السجل، ويصبح السجل الآن ذا قيمة 1.
انتهت العملية الثانية من التشغيل، وتستمر العملية الأولى في التشغيل من حيث توقفت:
- تقوم العملية الأولى بكتابة 1 في السجل، غير مدركة أن العملية الأخرى قد قامت بالفعل بتحديث القيمة في السجل إلى 1.
في المثال أعلاه، استدعى عمليتان أمر زيادة، إلا أن قيمة الكائن زادت من 0 إلى 1 فقط، بدلاً من 2 كما كان متوقعاً. وقد فُقدت إحدى عمليات الزيادة نتيجةً لعدم إمكانية ترتيب النظام خطياً.
يوضح المثال أعلاه الحاجة إلى التفكير بعناية في تطبيقات هياكل البيانات وكيف يمكن أن يكون للخطية تأثير على صحة النظام.
الذري
لتنفيذ كائن عداد خطي أو ذري، سنعدل تنفيذنا السابق بحيث تستخدم كل عملية P i سجلها الخاص R i . وهذا مشابه لكيفية عمل عدادات CRDT التي تعمل فقط على النمو .
تقوم كل عملية بزيادة القيمة وقراءة البيانات وفقًا للخوارزمية التالية:
زيادة:
- اقرأ القيمة في السجل R i .
- أضف واحدًا إلى القيمة.
- اكتب القيمة الجديدة مرة أخرى في R i
يقرأ:
- اقرأ السجلات R 1، R 2، ... R n .
- أعد مجموع جميع السجلات.
يحل هذا التطبيق مشكلة تطبيقنا الأصلي. في هذا النظام، تُجرى عمليات الزيادة بشكل خطي عند خطوة الكتابة. وتكون نقطة الخطية لعملية الزيادة هي عندما تكتب تلك العملية القيمة الجديدة في سجلها R i. أما عمليات القراءة، فتُجرى بشكل خطي حتى تصل إلى نقطة في النظام تكون فيها القيمة المُعادة من القراءة مساوية لمجموع جميع القيم المخزنة في كل سجل R i.
هذا مثال بسيط. في نظام حقيقي، قد تكون العمليات أكثر تعقيدًا، والأخطاء الناتجة دقيقة للغاية. على سبيل المثال، قد تُنفَّذ قراءة قيمة 64 بت من الذاكرة على أنها قراءتان متتاليتان لموقعين في الذاكرة، كل منهما 32 بت . إذا قرأ أحد العمليات أول 32 بت فقط، وقبل أن يقرأ الـ 32 بت الثانية، تغيرت القيمة في الذاكرة، فلن تحتوي على القيمة الأصلية ولا القيمة الجديدة، بل على قيمة مختلطة.
علاوة على ذلك، فإن الترتيب المحدد الذي يتم به تشغيل العمليات يمكن أن يغير النتائج، مما يجعل اكتشاف هذا الخطأ وإعادة إنتاجه وتصحيحه أمرًا صعبًا .
قارن واستبدل
تُوفّر معظم الأنظمة تعليمة مقارنة وتبديل ذرية تقرأ من موقع في الذاكرة، وتقارن القيمة مع قيمة "متوقعة" يُدخلها المستخدم، وتكتب قيمة "جديدة" إذا تطابقت القيمتان، وتُعيد ما إذا كان التحديث قد نجح. يُمكننا استخدام هذه التعليمة لإصلاح خوارزمية العداد غير الذرية كما يلي:
- اقرأ القيمة الموجودة في موقع الذاكرة؛
- أضف واحدًا إلى القيمة؛
- استخدم عملية المقارنة والتبديل لكتابة القيمة المتزايدة مرة أخرى؛
- أعد المحاولة إذا لم تتطابق القيمة المقروءة بواسطة عملية المقارنة والتبديل مع القيمة التي قرأناها في الأصل.
بما أن عملية المقارنة والتبديل تحدث (أو يبدو أنها تحدث) على الفور، فإذا قامت عملية أخرى بتحديث الموقع أثناء تقدمنا، فمن المؤكد أن عملية المقارنة والتبديل ستفشل.
جلب البيانات وزيادتها
تُوفّر العديد من الأنظمة تعليمة جلب وتزايد ذرية تقرأ من موقع في الذاكرة، وتكتب قيمة جديدة (القيمة القديمة زائد واحد) دون أي شروط، ثم تُعيد القيمة القديمة. يُمكننا استخدام هذه التعليمة لإصلاح خوارزمية العداد غير الذرية كما يلي:
- استخدم تقنية الجلب والزيادة لقراءة القيمة القديمة وكتابة القيمة المتزايدة مرة أخرى.
يُعدّ استخدام جلب البيانات وزيادة القيمة أفضل دائمًا (يتطلب عددًا أقل من عمليات الوصول إلى الذاكرة) لبعض الخوارزميات - مثل الخوارزمية الموضحة هنا - من استخدام المقارنة والتبديل، [ 6 ] على الرغم من أن هيرليهي أثبت سابقًا أن المقارنة والتبديل أفضل لبعض الخوارزميات الأخرى التي لا يمكن تنفيذها إطلاقًا باستخدام جلب البيانات وزيادة القيمة فقط. لذا، قد تكون تصميمات وحدات المعالجة المركزية التي تجمع بين جلب البيانات وزيادة القيمة والمقارنة والتبديل (أو تعليمات مكافئة) خيارًا أفضل من تلك التي تعتمد على إحداهما فقط. [ 6 ]
قفل
يتمثل نهج آخر في تحويل الخوارزمية البسيطة إلى قسم حرج ، لمنع الخيوط الأخرى من تعطيلها، باستخدام قفل . وهذا بدوره يُصلح خوارزمية العداد غير الذرية.
- الحصول على قفل، مما يمنع الخيوط الأخرى من تشغيل القسم الحرج (الخطوات 2-4) في نفس الوقت؛
- اقرأ القيمة الموجودة في موقع الذاكرة؛
- أضف واحدًا إلى القيمة؛
- اكتب القيمة المتزايدة مرة أخرى إلى موقع الذاكرة؛
- افتح القفل.
تعمل هذه الاستراتيجية كما هو متوقع؛ إذ يمنع القفل الخيوط الأخرى من تحديث القيمة حتى يتم تحريره. مع ذلك، بالمقارنة مع الاستخدام المباشر للعمليات الذرية، قد تعاني هذه الاستراتيجية من عبء إضافي كبير بسبب تنازع القفل. لتحسين أداء البرنامج، قد يكون من الأفضل استبدال المقاطع الحرجة البسيطة بعمليات ذرية للمزامنة غير الحظرية (كما فعلنا للتو مع العداد باستخدام المقارنة والتبديل وجلب القيمة وزيادتها)، بدلاً من العكس، ولكن لسوء الحظ، لا يُضمن تحسن ملحوظ، وقد تصبح الخوارزميات الخالية من الأقفال معقدة للغاية بحيث لا تستحق الجهد المبذول.
انظر أيضاً
مراجع
- 1 2 3 4 هيرليهي، موريس ب.؛ وينغ، جانيت م. (1990). "الخطية: شرط صحة للكائنات المتزامنة". معاملات ACM في لغات البرمجة والأنظمة . 12 (3): 463-492 . CiteSeerX 10.1.1.142.5315 . doi : 10.1145/78969.78972 . S2CID 228785 .
- ↑ شافيت، نير؛ تاوبنفيل، جادي (2016). "قابلية الحوسبة لهياكل البيانات المرنة: الطوابير والمكدسات كأمثلة" (ملف PDF) . الحوسبة الموزعة . 29 (5): 396-407 . doi : 10.1007/s00446-016-0272-0 . S2CID 16192696 .
- ↑ كيريسك، مايكل (7 سبتمبر 2018). واجهة برمجة لينكس . دار نشر نو ستارش. رقم ISBN 9781593272203– عبر كتب جوجل.
- ↑ "مقال تطوير أساسيات التزامن في معالجات ARM" .
- ↑ "عناصر التزامن الأساسية في ARMv8-A" . ص 6. تم الاطلاع عليه بتاريخ 14-12-2023 .
- 1 2 فيش، فيث؛ هندلر، داني؛ شافيت، نير (2004). "حول الضعف المتأصل في بدائيات التزامن الشرطي". وقائع الندوة السنوية الثالثة والعشرين لجمعية ACM حول مبادئ الحوسبة الموزعة - PODC '04 . نيويورك، نيويورك: ACM. ص 80-87 . doi : 10.1145/1011767.1011780 . ISBN 978-1-58113-802-3. S2CID 9313205 .
للمزيد من القراءة
- هيرليهي، موريس ب.؛ وينغ، جانيت م. (1987). "مسلمات الكائنات المتزامنة". وقائع الندوة الرابعة عشرة لجمعية ACM SIGACT-SIGPLAN حول مبادئ لغات البرمجة - POPL '87 . الصفحات 13-26 . doi : 10.1145/41625.41627 . ISBN 978-0-89791-215-0. S2CID 16017451 .
- هيرليهي، موريس ب. (1990). منهجية لتنفيذ هياكل البيانات عالية التزامن . المجلد 25، الصفحات 197-206 . CiteSeerX 10.1.1.186.6400 . doi : 10.1145/99164.99185 . ISBN 978-0-89791-350-8.
{{cite book}}تم|journal=تجاهله ( مساعدة ) - هيرليهي، موريس ب.؛ وينغ، جانيت م. (1990). "الخطية: شرط صحة للكائنات المتزامنة". معاملات ACM في لغات البرمجة والأنظمة . 12 (3): 463-492 . CiteSeerX 10.1.1.142.5315 . doi : 10.1145/78969.78972 . S2CID 228785 .
- أفير. "نماذج الاتساق القوي" . aphyr.com . أفير . تم الاطلاع عليه بتاريخ 13 أبريل 2018 .
- نماذج الاتساق
- معالجة المعاملات
- التحكم في التزامن
