مع التطوير القوي للإنترنت ، تواجه المزيد والمزيد من شركات الإنترنت مشاكل أمان متزامنة ناتجة عن توسيع حجم المستخدم. تركز هذه المقالة على العديد من آليات القفل الشائعة في تزامن Java.
1. قفل إيجابي
القفل المتحيز هو آلية تحسين القفل التي اقترحتها JDK1.6. الفكرة الأساسية هي أنه إذا لم يتنافس البرنامج ، فسيتم إلغاء عملية مزامنة مؤشر الترابط التي سبق الحصول عليها. وهذا يعني ، إذا تم الحصول على قفل بواسطة مؤشر ترابط ، فإنه يدخل وضع التحيز. عندما يطلب مؤشر الترابط القفل مرة أخرى ، ليست هناك حاجة لإجراء عمليات التزامن ذات الصلة ، وبالتالي توفير وقت التشغيل. إذا قامت مؤشرات الترابط الأخرى بتقديم طلبات القفل بينهما ، فإن القفل يخرج من وضع التحيز. باستخدام -xx:+useBiasedLocking في JVM
Package jvMProject ؛ import java.util.list ؛ import java.util.vector ؛ public class biased {public static list <integer> numberlist = new vector <integer> () ؛ public static void main (string [] args) {long begin = system.currentTimeMillis () ؛ عدد int = 0 ؛ int startNum = 0 ؛ بينما (العد <10000000) {numberlist.add (startNum) ؛ startNum+= 2 ؛ count ++ ؛ } نهاية طويلة = system.currentTimeMillis () ؛ system.out.println (نهاية begin) ؛ }}تهيئة المتجه ، وأضف 100،000،000 كائن عدد صحيح إليه ، ثم إخراج الفرق الزمني. يستخدم هذا لاختبار أداء الأقفال المتحيزة. أما لماذا يجب أن تستخدم المتجه بدلاً من ArrayList؟
نظرًا لأن ArrayList هو معطف الخيط ، فإن المتجه آمن لخيط الخيط. قد لا يكون هذا محددًا بما فيه الكفاية ، يمكنك إلقاء نظرة على الكود المصدري.
يتم تخزين جميع العمليات تقريبًا في المتجه ، في حين أن ArrayList لا ، لذا فإن المتجه آمن.
بعد ذلك ، دعنا نختبر مدى تأثير فتح الأقفال المتحيزة وعدم فتح الأقفال المتحيزة على أداء البرنامج.
قم بتكوين معلمات بدء تشغيل JVM (تشغيل قفل التحيز) إلى:
تكوين معلمات بدء تشغيل JVM (إغلاق قفل التحيز) إلى:
ممتاز! وقت تشغيل البرنامج الذي يمكّن القفل المتحيز هو أقصر بكثير. لديها مزايا معينة لتمكين الأقفال المتحيزة من عدم تمكين الأقفال المتحيزة. طريقة التزامن لتشغيل كائن في مؤشر ترابط واحد. في الواقع ، يمكن أيضًا فهمها بهذه الطريقة. عندما يكون هناك مؤشر ترابط واحد فقط يقوم بتشغيل كائن متجه مع طريقة التزامن ، سيتم تحويل العملية على المتجه إلى عملية على قائمة ArrayList.
لا يكون للقفل المتحيز تأثير تحسين قوي عندما يكون القفل قادرًا على التنافس ، لأن قدرًا كبيرًا من المنافسة سيؤدي إلى تبديل الخيط الذي يحمل القفل بشكل مستمر ، ومن الصعب على القفل البقاء في الوضع المتحيز. في هذا الوقت ، لا يؤدي استخدام القفل المتحيز إلى تحسين الأداء فحسب ، بل قد يقلل من أداء النظام. لذلك ، في حالة المنافسة الشرسة ، يمكنك محاولة استخدامها.
-xx: -usebiastedLocking المعلمة تعطل قفل التحيز.
2. قفل خفيف الوزن
في حالة فشل القفل المتحيز ، سيطلب جهاز Java Virtual من مؤشر الترابط التقدم بطلب للحصول على قفل خفيف الوزن. يتم تنفيذ قفل الوزن الخفيف داخل الجهاز الظاهري ويتم تنفيذه باستخدام كائن يصبح basicoBjectlock ، والذي يتكون من كائن أساسي ومؤشر كائن Java يحمل القفل. يتم وضع كائن BasicObjectlock في إطار مكدس Java. يتم أيضًا الحفاظ على حقل Display_header داخل كائن BasicLock ، والذي يتم استخدامه لدعم كلمة علامة رأس الكائن.
عندما يحمل مؤشر ترابط قفل كائن ، تكون معلومات علامة رأس الكائن على النحو التالي
[PTR | 00] مغلق
البتتين في النهاية هما 00 ، وكلمة العلامة بأكملها هي مؤشر لكائن BasicLock. نظرًا لأن كائن BasicObjectlock موجود في مكدس مؤشر الترابط ، يجب أن يشير المؤشر إلى مساحة مكدس مؤشر الترابط التي تحمل القفل. عندما يكون من الضروري تحديد ما إذا كان مؤشر الترابط يحتفظ بالكائن ، فمن الضروري فقط تحديد ما إذا كان مؤشر رأس الكائن ضمن نطاق عنوان المكدس في مؤشر الترابط الحالي. في الوقت نفسه ، يقوم Displared_header لكائن Basiclock بإعداد محتوى كلمة الكائن الأصلي ، ويشير حقل OBJ لكائن BasicObjectlock إلى رأس الكائن الذي يحمل القفل.
3. قفل الوزن الثقيل
عندما يفشل قفل الوزن الخفيف ، سيستخدم الجهاز الظاهري قفل الوزن الثقيل. عند استخدام أقفال الوزن الثقيل ، تكون كلمة علامة الكائن كما يلي:
[PTR | 10] شاشة
أثناء التشغيل ، يمكن تعليق الخيط على مستوى نظام التشغيل. إذا كان الأمر كذلك ، فسيتم زيادة تكلفة التبديل والاتصال بين المواضيع بشكل كبير.
4. قفل الدوران
يمكن أن يجعل قفل الدوران الخيط غير معلق عندما لا يحصل على القفل ، ولكن بدلاً من ذلك ، قم بالتبديل لتنفيذ حلقة فارغة (أي ما يسمى الدوران ، مما يعني تنفيذ الحلقة الفارغة نفسها). إذا تمكن الخيط من الحصول على القفل بعد عدة حلقات فارغة ، فسيستمر تنفيذها. إذا كان الخيط لا يزال لا يمكن الحصول على القفل ، فسيتم تعليقه.
بعد استخدام قفل الدوران ، يتم تقليل فرصة تعليق الخيط نسبيًا ، ويتم تعزيز اتساق تنفيذ مؤشر الترابط نسبيًا. لذلك ، يكون له أهمية إيجابية معينة بالنسبة للخيوط المتزامنة التي لا تنافسية للغاية مع الأقفال ولديها وقت قصير للغاية. ومع ذلك ، بالنسبة للبرامج المتزامنة التي تتنافس بشدة مع الأقفال والأقفال المفردة التي تشغلها وقتًا طويلاً ، غالبًا ما لا يستطيع قفل الدوران الحصول على القفل المقابل بعد انتظار الدوران. هذا لا يضيع وقت وحدة المعالجة المركزية فحسب ، ولكن أيضًا لديه العملية المعلقة في النهاية ، ولكن أيضًا تضيع موارد النظام.
في JDK1.6 ، يوفر الجهاز الظاهري Java المعلمة -xx:+USESPINNING لتمكين قفل الدوران ، ويستخدم المعلمة -xx: preblockspin لتعيين عدد مرات انتظار قفل الدوران.
بدءًا من JDK 1.7 ، يتم إلغاء معلمات قفل الدوران. لم يعد الجهاز الظاهري يدعم قفل الدوران الذي تم تكوينه للمستخدم. سيتم دائمًا تنفيذ قفل الدوران ، ويتم ضبط عدد أقفال الدوران تلقائيًا بواسطة الجهاز الظاهري.