باعتبارها أداة لمشاركة البيانات بشكل متزامن وضمان الاتساق، فإن الأقفال لها تطبيقات متعددة على منصة JAVA (مثل المزامنة وReentrantLock، وما إلى ذلك). توفر هذه الأقفال المكتوبة بالفعل الراحة لتطويرنا، ولكن نادرًا ما يتم ذكر الطبيعة المحددة للأقفال ونوعها. ستقوم هذه السلسلة من المقالات بتحليل أسماء الأقفال الشائعة وخصائصها ضمن JAVA للإجابة على أسئلتك.
4. قفل إعادة الدخول:
تتحدث هذه المقالة عن أقفال إعادة الدخول بالمعنى الواسع، وليس فقط ReentrantLock ضمن JAVA.
أقفال إعادة الدخول، والتي تسمى أيضًا الأقفال العودية، تعني أنه بعد حصول الوظيفة الخارجية لنفس الخيط على القفل، لا تزال الوظيفة العودية الداخلية تحتوي على رمز للحصول على القفل، ولكنها لا تتأثر.
في بيئة JAVA، يعد كل من ReentrantLock والمزامنة بمثابة أقفال إعادة الدخول.
فيما يلي أمثلة الاستخدام:
انسخ رمز الكود كما يلي:
اختبار الطبقة العامة يطبق Runnable{
الحصول على الفراغ العام المتزامن () {
System.out.println(Thread.currentThread().getId());
تعيين()؛
}
مجموعة الفراغ المتزامنة العامة () {
System.out.println(Thread.currentThread().getId());
}
@تجاوز
تشغيل الفراغ العام () {
يحصل()؛
}
public static void main(String[] args) {
اختبار ss=اختبار جديد();
موضوع جديد(ss).start();
موضوع جديد(ss).start();
موضوع جديد(ss).start();
}
}
النتائج النهائية لكلا المثالين صحيحة، أي أنه يتم إخراج نفس معرف مؤشر الترابط مرتين على التوالي.
والنتيجة هي كما يلي:
انسخ رمز الكود كما يلي:
عدد الخيوط: 8
عدد الخيوط: 8
عدد الخيوط: 10
عدد الخيوط: 10
رقم الموضوع: 9
رقم الموضوع: 9
الدور الأكبر لأقفال إعادة الدخول هو تجنب الجمود.
لنأخذ قفل الدوران كمثال.
انسخ رمز الكود كما يلي:
الطبقة العامة SpinLock {
Private AtomicReference<Thread> Owner =new AtomicReference<>();
قفل الفراغ العام (){
الموضوع الحالي = Thread.currentThread();
بينما(!owner.compareAndSet(null,current)){
}
}
فتح الفراغ العام (){
الموضوع الحالي = Thread.currentThread();
Owner.compareAndSet(current, null);
}
}
لأقفال الدوران:
1. إذا قام نفس الخيط باستدعاء القفل () مرتين، فسيؤدي ذلك إلى استدعاء موضع القفل للمرة الثانية. إذا حدث طريق مسدود، فهذا يعني أن القفل لم يعد يدخل. (في وظيفة القفل، يجب عليك التحقق مما إذا كان الخيط هو الخيط الذي حصل على القفل)
2. إذا تم حل المشكلة رقم 1، فسيتم تحرير القفل عند استدعاء unlock() لأول مرة. لا ينبغي أن يتم تحرير القفل فعليًا.
(باستخدام أوقات العد للإحصائيات)
وبعد التعديل أصبح كما يلي:
انسخ رمز الكود كما يلي:
الطبقة العامة SpinLock1 {
Private AtomicReference<Thread> Owner =new AtomicReference<>();
عدد صحيح خاص = 0؛
قفل الفراغ العام (){
الموضوع الحالي = Thread.currentThread();
إذا (الحالي==owner.get()) {
العد++;
يعود ؛
}
بينما(!owner.compareAndSet(null,current)){
}
}
فتح الفراغ العام (){
الموضوع الحالي = Thread.currentThread();
إذا (الحالي==owner.get()){
إذا (العد!=0){
عدد--؛
}آخر{
Owner.compareAndSet(current, null);
}
}
}
}
قفل الدوران هذا هو قفل إعادة الدخول.