الإشارة في Java هي أداة مساعدة للمزامنة تعمل على تقييد عدد سلاسل العمليات التي يمكنها الوصول إلى مورد مشترك في أي وقت محدد. وهو جزء من الحزمة java.util.concurrent ويستخدم لإدارة الوصول المتزامن إلى الموارد، مثل الملفات أو قواعد البيانات أو اتصالات الشبكة.
تتحكم الإشارة في الوصول إلى عدد محدد من التصاريح. يمثل كل تصريح الحق في الوصول إلى مورد معين. تقوم الإشارة بتتبع عدد التصاريح المتاحة، والتي تحدد عدد سلاسل العمليات التي يمكنها الوصول إلى المورد في وقت واحد.
السماح: رمز مميز أو تذكرة تسمح لسلسلة المحادثات بمتابعة الوصول إلى مورد مشترك.
عند إنشاء إشارة، فإنك تحدد عدد التصاريح المتاحة. يحدد هذا الرقم عدد سلاسل العمليات التي يمكنها الوصول إلى المورد بشكل متزامن.
قبل أن يتمكن الخيط من الوصول إلى المورد، يجب عليه الحصول على تصريح من الإشارة. يتم ذلك باستخدام طريقة acquire().
اكتساب: يتم استدعاء هذه الطريقة عندما يريد مؤشر ترابط الوصول إلى المورد. في حالة توفر تصريح، تقوم الإشارة بتقليل عدد التصاريح المتاحة وتسمح بمتابعة مؤشر الترابط. إذا لم تتوفر أي تصاريح، فسيتم حظر مؤشر الترابط حتى يصبح التصريح متاحًا.
سلوك الحظر: في حالة عدم توفر تصاريح، سيتم حظر الخيط الذي يستدعي اكتساب () (أي سينتظر) حتى يصدر مؤشر ترابط آخر تصريحًا.
بمجرد انتهاء سلسلة المحادثات من استخدام المورد، يجب أن تقوم بتحرير التصريح لجعله متاحًا لسلاسل المحادثات الأخرى. يتم ذلك باستخدام طريقة release() .
الإصدار: تعمل هذه الطريقة على زيادة عدد التصاريح المتاحة. إذا كان هناك أي سلاسل تنتظر الحصول على تصريح، فسيتم إلغاء حظر أحدهم والسماح له بالحصول على التصريح.
هناك نوعان من الإشارات في جافا:
لفهم كيفية عمل الإشارات بشكل أفضل، دعونا نلقي نظرة على التنفيذ العملي. سنقوم بإنشاء سيناريو بسيط حيث تحاول سلاسل رسائل متعددة الوصول إلى مورد محدود.
import java.util.concurrent.Semaphore; public class SemaphoreDemo { // Creating a semaphore with 3 permits private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { // Creating and starting 6 threads for (int i = 1; i2.2 شرح الكود
في هذا المثال، قمنا بإنشاء إشارة بثلاثة تصاريح، مما يعني أن ثلاثة سلاسل فقط يمكنها الوصول إلى القسم الحرج من الكود في أي وقت محدد. نقوم بعد ذلك بإنشاء ستة سلاسل رسائل، تحاول جميعها الحصول على تصريح. بمجرد حصول الخيط على تصريح، فإنه يحاكي بعض الأعمال من خلال النوم لمدة ثانيتين قبل إطلاق التصريح.
2.3 مراقبة المخرجات
عند تشغيل الكود أعلاه، سيبدو الإخراج كما يلي:
Worker 1 is trying to acquire a permit... Worker 1 acquired a permit. Worker 2 is trying to acquire a permit... Worker 2 acquired a permit. Worker 3 is trying to acquire a permit... Worker 3 acquired a permit. Worker 4 is trying to acquire a permit... Worker 5 is trying to acquire a permit... Worker 6 is trying to acquire a permit... Worker 1 is releasing a permit. Worker 4 acquired a permit. Worker 2 is releasing a permit. Worker 5 acquired a permit. Worker 3 is releasing a permit. Worker 6 acquired a permit.هنا، تحصل المواضيع الثلاثة الأولى على التصاريح بنجاح وتبدأ مهامها. يجب أن تنتظر الخيوط المتبقية حتى يتم إصدار تصريح قبل أن تتمكن من المتابعة.
2.4 حالات الاستخدام العملي
تعتبر الإشارات مفيدة بشكل خاص في السيناريوهات التي تحتاج فيها إلى تحديد عدد عمليات الوصول المتزامنة إلى مورد معين، مثل:
على الرغم من أن الإشارات هي أداة قوية، إلا أنها تأتي مع مجموعة من المزايا والعيوب الخاصة بها.
المرونة: تسمح الإشارات بالتحكم الدقيق في الوصول إلى الموارد من خلال سلاسل رسائل متعددة.
قابلية التوسع: يمكن للإشارات المرورية إدارة الوصول إلى عدد كبير من الموارد بسهولة.
العدالة: يمكن تكوين الإشارات لضمان حصول سلاسل الرسائل على التصاريح بطريقة عادلة.
التعقيد : يمكن أن يؤدي استخدام الإشارات إلى تعقيد التعليمات البرمجية الخاصة بك، مما يجعل تصحيح الأخطاء أكثر صعوبة.
التوقف التام : إذا لم يتم التعامل معها بشكل صحيح، يمكن أن تؤدي الإشارات إلى طريق مسدود حيث يتم حظر سلاسل الرسائل إلى أجل غير مسمى في انتظار التصاريح.
لتجنب الأخطاء الشائعة وتحقيق أقصى استفادة من الإشارات، خذ في الاعتبار أفضل الممارسات التالية:
بدلاً من استخدام اكتساب()، الذي يحظر إلى أجل غير مسمى، يمكنك استخدام TryAcquire() لمحاولة الحصول على تصريح بعد انتهاء المهلة. وهذا يمنع سلاسل الرسائل من أن تتعثر في الانتظار.
if(semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS)) { try { // Critical section } finally { semaphore.release(); } }
لتجنب تسرب الموارد، قم دائمًا بإصدار التصريح في كتلة أخيرًا. وهذا يضمن تحرير التصريح حتى في حالة حدوث استثناء.
إذا كنت تحتاج فقط إلى قفل مورد وإلغاء قفله لسلسلة رسائل واحدة، ففكر في استخدام ReentrantLock أو المزامنة بدلاً من الإشارة الثنائية.
تعد الإشارات أداة قوية لإدارة التزامن في Java، مما يسمح لك بالتحكم في عدد سلاسل الرسائل التي تصل إلى مورد مشترك. باتباع التقنيات وأفضل الممارسات الموضحة في هذه المقالة، يمكنك تنفيذ الإشارات بشكل فعال في تطبيقات Java الخاصة بك لضمان إدارة الموارد بشكل آمن وفعال.
إذا كانت لديك أية أسئلة أو ترغب في مشاركة تجاربك الخاصة مع الإشارات، فلا تتردد في التعليق أدناه!
اقرأ المشاركات المزيد على : تقنيات إدارة التزامن في Java باستخدام الإشارات
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3