مشغول بالانتظار
في علوم الحاسوب وهندسة البرمجيات ، يُعدّ الانتظار النشط أو التكرار النشط أو الدوران أسلوبًا يقوم فيه المعالج بالتحقق بشكل متكرر من صحة شرط ما، مثل توفر مدخلات لوحة المفاتيح أو إمكانية قفل النظام . كما يُمكن استخدام الدوران لتوليد تأخير زمني عشوائي، وهو أسلوب كان ضروريًا في الأنظمة التي تفتقر إلى طريقة للانتظار لفترة زمنية محددة. تختلف سرعات المعالجات اختلافًا كبيرًا من جهاز لآخر، خاصةً وأن بعض المعالجات مصممة لضبط سرعتها ديناميكيًا بناءً على عبء العمل الحالي. [ 1 ] ونتيجةً لذلك، قد يُنتج الدوران كأسلوب للتأخير الزمني نتائج غير متسقة أو حتى غير متوقعة على أنظمة مختلفة، ما لم يتم تضمين كود لتحديد الوقت الذي يستغرقه المعالج لتنفيذ حلقة "عدم القيام بأي شيء" ، أو ما لم يتحقق كود التكرار صراحةً من ساعة الوقت الحقيقي .
في معظم الحالات، يُعتبر استخدام الأقفال الدورانية نمطًا سيئًا ويجب تجنبه، [ 2 ] حيث يُهدر وقت المعالج الذي كان من الممكن استخدامه لتنفيذ مهمة أخرى في نشاط غير مُجدٍ. قد يكون استخدام الأقفال الدورانية استراتيجيةً صالحةً في ظروف معينة، لا سيما عند تطبيق الأقفال الدورانية ضمن أنظمة التشغيل المصممة للعمل على أنظمة المعالجة المتعددة المتناظرة (SMP) .
مثال
توضح أمثلة كود جافا التالية خيطين يتشاركان عددًاi صحيحًا عامًا . يستخدم الخيط الأول الانتظار النشط للتحقق من حدوث تغيير في قيمة i:
package org.wikipedia.examples ;استيراد java.util.concurrent.atomic.AtomicInteger ؛public class Example { // عدد صحيح ذري مشترك بين الخيوط static AtomicInteger i = new AtomicInteger ( 0 );public static void main ( String [] args ) throws InterruptedException { // Thread f1: waits for i to change from 0 Thread t1 = new Thread (() -> { int local ; while (( local = i . get ()) == 0 ) { // Busy-wait (spinlock) } System . out . printf ( "i's value has changed to %d.%n" , local ); });// الخيط f2: يُغيّر قيمة i بعد 10 ثوانٍ Thread t2 = new Thread (() -> { int local = 99 ; try { Thread . sleep ( 10_000 ); // انتظر 10 ثوانٍ } catch ( InterruptedException e ) { Thread . currentThread (). interrupt (); return ; } i . set ( local ); System . out . printf ( "t2 قام بتغيير قيمة i إلى %d.%n" , local ); });// بدء تشغيل الخيوط t1.start ( ); t2.start ( );// انتظر حتى تنتهي الخيوط t1.join ( ) ; t2.join ( );System.out.println ( " انتهت جميع العمليات. " ) ; } }في حالة استخدام كهذه، يمكن للمرء أن يفكر في استخدام متغيرات الشرط أيضًا.
البدائل
تُوفّر معظم أنظمة التشغيل ومكتبات تعدد الخيوط مجموعة متنوعة من استدعاءات النظام التي تُوقف العملية مؤقتًا عند وقوع حدثٍ ما، مثل الحصول على قفل، أو تغييرات المؤقت، أو توفر الإدخال/الإخراج ، أو الإشارات . يُنتج استخدام هذه الاستدعاءات عمومًا أبسط النتائج وأكثرها كفاءةً وعدالةً، ويضمن عدم حدوث تضارب في الوصول . يتحقق استدعاء واحد من الحدث، ويُعلم المُجدول به، ويُضيف حاجزًا للذاكرة عند الاقتضاء، وقد يُنفّذ عملية إدخال/إخراج مطلوبة قبل العودة. يُمكن للعمليات الأخرى استخدام وحدة المعالجة المركزية أثناء توقف العملية المُستدعِية. يُزوّد المُجدول بالمعلومات اللازمة لتطبيق توريث الأولوية أو آليات أخرى لتجنب الحرمان من الموارد .
يمكن تقليل استهلاك موارد المعالج بشكل كبير من خلال استخدام دالة تأخير (مثلاً، `useSupporting` sleep()) الموجودة في معظم أنظمة التشغيل. تعمل هذه الدالة على إيقاف تنفيذ الخيط مؤقتًا لفترة زمنية محددة، لا يستهلك خلالها الخيط أي وقت من المعالج. إذا كانت الحلقة تتحقق من أمر بسيط، فستقضي معظم وقتها في وضع السكون، وبالتالي ستستهلك القليل جدًا من وقت المعالج.
إذا كان التأخير قصيرًا، فغالبًا ما توجد وظيفة أخرى ببساطة للتخلي عن المعالج، مما يؤدي إلى التخلي عن التحكم للعمليات الأخرى، ولكن دون انتظار أي وقت.
في البرامج التي لا تنتهي أبدًا (مثل أنظمة التشغيل)، يمكن تنفيذ الانتظار النشط اللانهائي باستخدام القفزات غير المشروطة كما هو موضح في صيغة NASM التالية :
اقفز $سينتقل المعالج المركزي تلقائيًا إلى موقعه الحالي إلى الأبد. يمكن استبدال عملية انتظار نشطة كهذه بما يلي:
النوم: hlt jmp sleepللمزيد من المعلومات، انظر HLT (تعليمات x86) .
الاستخدام المناسب
في البرمجة منخفضة المستوى، قد يكون استخدام الانتظار النشط مرغوبًا فيه. قد لا يكون من المرغوب فيه أو العملي تطبيق معالجة تعتمد على المقاطعات لكل جهاز، خاصةً تلك التي نادرًا ما يتم الوصول إليها. أحيانًا يكون من الضروري كتابة بيانات تحكم معينة إلى الجهاز، ثم جلب حالة الجهاز الناتجة عن عملية الكتابة، وهي حالة قد لا تصبح صالحة إلا بعد مرور عدد من دورات المعالج. يمكن للمبرمج استدعاء دالة تأخير من نظام التشغيل، لكن ذلك قد يستغرق وقتًا أطول من الوقت المستغرق في انتظار الجهاز لبضع دورات ساعة لإعادة حالته.
انظر أيضاً
مراجع
- ↑ "تقنية Intel Turbo Boost" .
- ↑ "لماذا لا ينبغي استخدام فئة النوع 'volatile'" . مؤرشف من الأصل بتاريخ 2017-10-04 . تم الاطلاع عليه بتاريخ 2013-06-10 .
روابط خارجية
- وصف من المواصفات الأساسية لمجموعة Open Group، الإصدار 6، معيار IEEE 1003.1، إصدار 2004
- مقال بعنوان " أقفال الدوران على مستوى المستخدم - الخيوط والعمليات والتواصل بين العمليات " بقلم جيرت بودارت
- مرجع فئة قفل الدوران النمساوي، مؤرشف بتاريخ 14 مايو 2011 في أرشيف الإنترنت (Wayback Machine) .
- الأنماط المضادة
- التحكم في التزامن
