مقدمة
يعرف أي شخص على دراية ببرمجة Java Conversion أن القاعدة التي تحدث قبل (HB) في JMM (نموذج الذاكرة JMM) ، والتي تحدد نظام العمليات متعددة الخيوط Java ، مما يمنع تأثير إعادة ترتيب البرمجيات على نتائج البرنامج.
هناك قاعدة "عندما قبل" في لغة جافا. إنها علاقة ترتيب جزئي بين عمليتين محددة في نموذج ذاكرة Java. في حالة حدوث العملية "أ" أولاً في العملية "ب" ، فهذا يعني أنه قبل حدوث العملية ب ، يمكن ملاحظة تأثير التشغيل A عن طريق العملية ب. "التأثير" يتضمن تعديل قيمة المتغيرات المشتركة في الذاكرة ، وإرسال الرسائل ، وطرق الاتصال ، وما إلى ذلك ، والتي لا علاقة لها بتسلسل الحدوث في الوقت المناسب. هذا المبدأ مهم بشكل خاص. هذا هو الأساس الرئيسي للحكم على ما إذا كانت هناك منافسة في البيانات وما إذا كانت مؤشرات الترابط آمنة.
وفقا للبيان الرسمي:
عندما تتم قراءة متغير من قبل مؤشرات ترابط متعددة ويكتب بواسطة مؤشر ترابط واحد على الأقل ، إذا لم تكن هناك علاقة HB بين عمليات القراءة والكتابة ، ستنشأ مشاكل سباق البيانات.
للتأكد من أن الخيط الذي يعمل B يرى نتيجة العملية A (بغض النظر عما إذا كان A و B في نفس الخيط) ، يجب استيفاء مبدأ HB بين A و B ، وإذا لم يكن الأمر كذلك ، فقد يؤدي ذلك إلى إعادة ترتيب.
عندما تكون علاقة HB مفقودة ، قد تحدث مشكلات إعادة ترتيب.
ما هي قواعد HB؟
الجميع على دراية بهذا. سيتم تقديم معظم الكتب والمقالات. دعنا نراجعها باختصار هنا:
من بينهم ، لقد جربت قواعد التسليم ، وهو أمر بالغ الأهمية. كيفية استخدام قواعد التسليم بكفاءة هو مفتاح تحقيق التزامن.
بعد ذلك ، اشرح HB من منظور آخر: عندما تعمل عملية A HB B ، فإن نتيجة التشغيل للعملية A على المتغير المشترك تكون مرئية للعملية B.
في الوقت نفسه ، إذا كانت العملية B HB تعمل C ، فإن نتيجة تشغيل العملية A على المتغير المشترك تكون مرئية للعملية B.
مبدأ تحقيق الرؤية هو بروتوكول ذاكرة التخزين المؤقت وحاجز الذاكرة. يتم تحقيق الرؤية من خلال بروتوكولات تماسك ذاكرة التخزين المؤقت وحواجز الذاكرة.
كيفية تحقيق التزامن؟
في كتاب دوغ ليا "Java Concurrency in Practice" ، الوصف التالي هو:
يذكر الكتاب: من خلال الجمع بين بعض قواعد HB ، يمكن تحقيق رؤية متغير محمي غير مؤمن.
ولكن نظرًا لأن هذه التقنية حساسة لترتيب العبارات ، فهي عرضة للأخطاء.
بعد ذلك ، سيوضح المؤلف كيفية مزامنة متغير من خلال القواعد المتقلبة وقواعد طلب البرنامج.
دعنا نكون مثالًا مألوفًا:
الفئة threadprintdemo {static int num = 0 ؛ العلم المنطقي الثابت الثابت = خطأ ؛ public static void main (string [] args) {thread t1 = new thread (() -> {for (؛ 100> num ؛) {if (! flag && (num == 0 || ++ num ٪ 2 == 0)) {system.out.println (num) ؛ flag =}}}) ؛ Thread T2 = New Thread (() -> {for (؛ 100> num ؛) {if (flag && (++ num ٪ 2! = 0)) {system.out.println (num) ؛ flag = false ؛}}}) ؛ t1.start () ؛ t2.start () ؛ }}الغرض من هذا الرمز هو طباعة الأرقام 0 - 100 بين موضوعين.
يجب أن يقول الطلاب الذين يعرفون البرمجة المتزامنة أن متغير NUM هذا لا يستخدم متطايرة ، وسيكون هناك مشاكل في الرؤية ، أي ، لقد تم تحديث مؤشر ترابط T1 ، ولا يمكن لخيط T2 إدراكه.
هاها ، اعتقد المؤلف ذلك في البداية ، ولكن في الآونة الأخيرة من خلال دراسة قواعد HB ، وجدت أنه من المقبول إزالة التعديل المتقلبة لـ NUM.
دعنا نحللها ووجه الملصق صورة:
دعونا نحلل هذا الشكل:
ملاحظة: تضمن قاعدة HB أن تكون نتائج العملية السابقة مرئية للعملية التالية.
لذلك ، في التطبيق المذكور أعلاه ، يدرك الخيط B تمامًا تعديل NUM بواسطة الموضوع A - حتى لو لم يتم تعديل NUM مع متقلبة.
وبهذه الطريقة ، نستخدم مبدأ HB لتحقيق التشغيل المتزامن لمتغير ، أي في بيئة متعددة الخيوط ، نضمن أمان التعديل المتزامن للمتغيرات المشتركة. ولا توجد جافا بدائية لهذا المتغير: متطايرة ومزامنة و CAS (على افتراض أنه مهم).
قد يبدو هذا غير آمن (آمن بالفعل) وقد لا يبدو من السهل فهمه. لأن كل هذا يتم تنفيذه بواسطة بروتوكول ذاكرة التخزين المؤقت وحاجز الذاكرة في HB الأساسي.
قواعد أخرى لتحقيق التزامن
التنفيذ باستخدام قواعد إنهاء مؤشرات الترابط:
ثابت int a = 1 ؛ الفراغ الثابت العام (String [] args) {thread tb = new thread (() -> {a = 2 ؛}) ؛ THEARD TA = New Thread (() -> {try {tb.join () ؛} catch (interruptedException e) {// no} system.out.println (a) ؛}) ؛ ta.start () ؛ tb.start () ؛ } استخدم قواعد بدء سلسلة الرسائل للتنفيذ:
ثابت int a = 1 ؛ public static void main (string [] args) {thread tb = new thread (() -> {system.out.println (a) ؛}) ؛ THELE TA = New Thread (() -> {tb.start () ؛ a = 2 ؛}) ؛ ta.start () ؛ }يمكن أن تضمن هاتان العمليتان أيضًا رؤية المتغير أ.
انها حقا يفسد المفهوم السابق. في المفهوم السابق ، إذا لم يتم تعديل المتغير عن طريق متقلبة أو نهائية ، فإن قراءته وكتابته تحت متعدد الخيوط غير آمن بالتأكيد - لأنه سيكون هناك مخبأ ، مما يؤدي إلى قراءةها ليست الأحدث.
ومع ذلك ، باستخدام HB ، يمكننا تحقيق ذلك.
لخص
على الرغم من أن عنوان هذه المقالة هو إدراك العمليات المتزامنة للمتغيرات المشتركة من خلال الحدوث قبل أن يحدث ، فإن الغرض الرئيسي هو فهم الحدوث بشكل أعمق. إن فهم المفهوم الذي حدث قبله هو في الواقع ضمان ترتيب العملية السابقة للعملية التالية وتؤدي رؤية العملية إلى بيئة متعددة الخيوط.
في الوقت نفسه ، من خلال استخدام قواعد متعدية مرنًا ثم الجمع بين القواعد ، يمكن مزامنة مؤشر ترابط - يمكن أن يضمن تنفيذ المتغير المشترك المحدد دون استخدام البدائل أيضًا التأكد من الرؤية. على الرغم من أن هذا لا يبدو من السهل القراءة للغاية ، إلا أنها أيضًا محاولة.
يمنح دوغ ليا ممارسة JUC حول كيفية الجمع بين القواعد لتحقيق التزامن.
على سبيل المثال ، تزامن الفئة الداخلية للنسخة القديمة من مستقبلات FutureTask (اختفت) ، وتعديل المتغير المتطاير من خلال طريقة tryreleaseshared ، ويقرأ TryAcquireshared المتغير المتطاير ، الذي يستخدم القواعد المتطايرة ؛
يستفيد هذا من قواعد طلب البرنامج من خلال تعيين متغير نتيجة غير متطايرة قبل TryReleaseshared ثم قراءة متغير النتيجة بعد TryAcquireshared.
هذا يضمن رؤية متغير النتيجة. على غرار مثالنا الأول: استخدام قواعد ترتيب البرنامج والقواعد المتقلبة لتحقيق الرؤية المتغيرة العادية.
قال دوغ ليا نفسه إن تقنية "استخدام المساعدة" هذه عرضة للغاية للأخطاء ويجب استخدامها بحذر. ولكن في بعض الحالات ، هذا النوع من "الرافعة المالية" معقولة للغاية.
في الواقع ، plockingqueue أيضا "المستخدمة" القواعد قبل. تذكر قاعدة فتح؟ عند حدوث فتح ، يجب أن تكون العناصر الداخلية مرئية.
هناك عمليات أخرى في مكتبة الفصل والتي "تستخدم" مبدأ الحدث: الحاويات المتزامنة ، وترقد التراجع ، والرملة ، والمستقبل ، والمنفذ ، والغراب ، والمبادل ، إلخ.
باختصار ، باختصار:
مبدأ الحدوث قبل جوهر JMM. فقط عندما يتم استيفاء مبدأ HB ، يمكن التأكد من الرؤية ، وإلا فإن المترجم سيعيد ترتيب الرمز. HB حتى يحدد قواعد القفل والمتقلب.
من خلال مزيج مناسب من قواعد HB ، يمكن تحقيق الاستخدام الصحيح للمتغيرات المشتركة العادية.
حسنًا ، ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.