قد يكون العديد من الأصدقاء قد سمعوا عن الكلمة الرئيسية المتطايرة وربما استخدموها. قبل Java 5 ، كانت كلمة رئيسية مثيرة للجدل ، حيث أن استخدامها في البرامج غالبًا ما أدى إلى نتائج غير متوقعة. فقط بعد أن استعادت Java 5 الكلمة الرئيسية المتطايرة حيويتها. على الرغم من أن الكلمة الرئيسية المتطايرة سهلة الفهم حرفيًا ، إلا أنه ليس من السهل استخدامها جيدًا.
1. مقدمة
يوفر JMM تعريفًا متغيرًا متغيرًا ، كتل نهائية متزامنة لضمان الرؤية.
بالنسبة للمتغيرات التي تم تعديلها باستخدام متطاير ، سيقرأ مؤشر الترابط القيمة الأكثر تعديلًا للمتغير في كل مرة يستخدم فيها المتغير. يتم إساءة استخدام التقلب بسهولة واستخدامها للعمليات الذرية. لقد كتبت بعض أمثلة الاختبار ، يمكنك تجربة ذلك.
2. البرنامج الرئيسي
الفئة العامة الرئيسية {public static void main (string [] args) remrows interruptededException {list <furns> lindlist = new ArrayList <froof> () ؛ for (int i = 0 ؛ i <10 ؛ ++ i) {thread thread = new thread (new runnable () {overridepublic run () {single.holder.instance.add () ؛}}) ؛ قائمة المواضيع3. اختبار وضع Singleton
1. لا متقلبة ، لا متزامن
الفئة الفردية {public int x = 0 ؛ public void add () {try {timeUnit.milliseconds.sleep (50) ؛} catch (InterruptedException e) {e.printstacktrace () ؛} ++ this.x ؛نتائج الإخراج: 8 و 9 و 10 ظهرت جميعها. يمكنك تشغيل المزيد وتجربة المزيد وستجد نتائج مختلفة.
2. هناك متقلبة ، ولكن لا يوجد متزامن
الفئة الفردية {public platile int x = 0 ؛ void public add () {try {timunit.milliseconds.sleep (50) ؛} catch (interruptedException e) {E.PrintStackTrace () ؛} ++ this.x ؛نتيجة الإخراج: الحد الأقصى لعدد الأحداث هو 9 و 10.
3. لا متقلبة ، متزامنة
الفئة الفردية {public int x = 0 ؛ void المزامنة العامة add () {try {timunit.milliseconds.sleep (50) ؛} catch (interruptedException e) {E.PrintStackTrace () ؛} ++ this.x ؛نتيجة الإخراج: بغض النظر عن عدد المرات التي تعمل فيها ، سيكون 10.
4. حول تطبيق متقلبة في DCL (قفل التحقق المزدوج)
الطبقة العامة Lazysingleton {private int somefield ؛ مثيل خاص ثابت lazysingleton ؛ private lazysingleton () {this.somefield = new random (). nextint (200) +1 ؛ // (1)} lazysingleton getInstance () {if (مثيل == null) {// (2) Synchronized (lazysingleton.class) {// (3) if (exate == null) {// (4) مثيل = new lazysingleton () ؛ // (5)}}} مثيل الإرجاع ؛ // (6)} public int getSomeField () {return this.somefield ؛ // (7)}}بادئ ذي بدء ، اسمحوا لي أن أشرح لماذا لا تعمل طريقة الكتابة هذه في Java!
لنفترض أن الموضوع الأول أسمي طريقة getInstance () لأول مرة ، ثم يقوم Thread II أيضًا باستدعاء طريقة getInstance () وطريقة GetOmefield (). ما نريد أن نشرحه هو أن بيان الموضوع I (1) ليس يحدث قبل بيان الموضوع II (7). عندما يقوم الموضوع II بتنفيذ البيان (2) من طريقة getInstance () ، نظرًا لأن الوصول إلى المثيل ليس في الكتلة المتزامنة ، فقد يلاحظ الموضوع II أو لا يلاحظ كتابة الخيط الأول إلى المثيل في العبارة (5) ، أي قد تكون قيمة المثيل فارغة أو غير فارغة. نفترض أولاً أن قيمة المثيل ليست فارغة ، لذلك نلاحظ أن الخيط الأول يكتب المثيل. في هذا الوقت ، سيقوم الموضوع II بتنفيذ العبارة (6) وإرجاع قيمة هذا المثيل مباشرة ، ثم اتصل بطريقة GetSomeField () على هذه الحالة. وتسمى هذه الطريقة أيضًا دون أي مزامنة. لذلك ، يتم استدعاء عملية الموضوع II بأكملها دون التزامن. هذا يدل على أنه لا توجد علاقة قبل البيان (1) من الموضوع الأول والبيان (7) من الموضوع الثاني. هذا يعني أن الموضوع II قد لا يكون قادرًا على مراقبة القيمة المكتوبة بواسطة الموضوع الأول إلى بعضها في العبارة (1). هذه هي مشكلة DCL. إنه أمر مثير للسخرية ، أليس كذلك؟ كان يهدف DCL في الأصل إلى الهروب من التزامن ، وقد حقق هذا الهدف. وبسبب ذلك بالتحديد أنه تمت معاقبته في النهاية. هناك أخطاء خطيرة في مثل هذه البرامج ، على الرغم من أن احتمال اكتشاف هذا الخطأ هو بالتأكيد أقل بكثير من احتمال الفوز باليانصيب ، وهو عابر. ما هو أكثر رعبا هو أنه حتى لو حدث ذلك ، فلن تعتقد أنه كان سببها DCL.
أفهم أن كلا من الموضوع I و Thread II لديهما تخزين العمل الخاص بهما. بعد أن أقوم بإنشاء المثيل ، فإن وقت التحديث إلى الذاكرة غير مؤكد ، لذلك من الممكن تمامًا أن لا يمكن للمعلومات II مراقبة القيمة المكتوبة بواسطة الموضوع الأول إلى بعضها في العبارة (1).
لذلك نظرًا لوجود قاعدة إضافية تم إضافتها في Java 5:
• اكتب عملية إلى الحقل المتقلبة التي تحدث قبل عمليات القراءة اللاحقة إلى نفس الحقل.
باستخدام هذه القاعدة ، يمكننا أن نعلن عن مثيل متقلبة ، أي: مثيل Lazysingleton ثابت خاص ؛
وفقًا لهذه القاعدة ، يمكننا الحصول على بيان الموضوع I (5) -> الجملة من الموضوع II (2) (أي الخيط) ، وفقًا لقاعدة الخيوط الواحدة ، فإن بيان الموضوع I (1) -> الجملة من الموضوع I (5) والجملة من الموضوع II (2) - قيمة الموضوع الأول إلى بعضها في العبارة (1) ، ويمكن للبرنامج الحصول على السلوك الصحيح.
الملحق: قبل Java5 ، لا يوجد فرق بين الدلالات المتزامنة للحقل النهائي والمتغيرات الأخرى. في Java5 ، بمجرد تعيين المتغير النهائي في المُنشئ (شريطة أن لا يتم تسريب هذا المرجع في المنشئ) ، سترى مؤشرات الترابط الأخرى بالتأكيد القيم المحددة في المنشئ. تكمن مشكلة DCL في أن نرى القيمة الافتراضية لمتغير العضو للكائن ، حتى نتمكن من تعيين متغير O.
المحتوى أعلاه هو معرفة الكلمات الرئيسية المتطايرة في Java التي قدمها لك المحرر. آمل أن يكون ذلك مفيدًا للجميع!