يتم استخدام الكلمة الأساسية المتقلبة لتعديل قيمة المتغير بواسطة سلاسل رسائل مختلفة. يتم استخدامه أيضًا لجعل سلاسل المحادثات آمنة. هذا يعني أنه يمكن لخيوط متعددة استخدام طريقة ومثيل للفئات في نفس الوقت دون أي مشكلة. يمكن استخدام الكلمة الأساسية المتقلبة إما مع النوع البدائي أو الكائنات.
لا تقوم الكلمة الأساسية المتغيرة بتخزين قيمة المتغير مؤقتًا وتقرأ دائمًا المتغير من الذاكرة الرئيسية. لا يمكن استخدام الكلمة الأساسية المتقلبة مع الفئات أو الأساليب. ومع ذلك، يتم استخدامه مع المتغيرات. كما أنه يضمن الرؤية والنظام. يمنع المترجم من إعادة ترتيب التعليمات البرمجية.
مثال على اسم المستخدم
يمكن أن تتغير محتويات سجل جهاز معين في أي وقت، لذلك تحتاج إلى الكلمة الأساسية المتقلبة لضمان عدم تحسين عمليات الوصول هذه بواسطة المترجم.
مثال
class Test { static int var=5; }
في المثال أعلاه، افترض أن هناك خيطين يعملان في نفس الفئة. يعمل كلا الخيطين على معالجات مختلفة حيث يكون لكل خيط نسخته المحلية من var. إذا قام أي خيط بتعديل قيمته، فلن ينعكس التغيير على الأصل في الذاكرة الرئيسية. يؤدي إلى عدم تناسق البيانات لأن مؤشر الترابط الآخر ليس على علم بالقيمة المعدلة.
class Test { static volatile int var =5; }
في المثال أعلاه، المتغيرات الثابتة هي أعضاء فئة مشتركة بين كافة الكائنات. توجد نسخة واحدة فقط في الذاكرة الرئيسية. لن يتم تخزين قيمة المتغير المتطاير في ذاكرة التخزين المؤقت أبدًا. سيتم إجراء جميع عمليات القراءة والكتابة من وإلى الذاكرة الرئيسية.
متى تستخدمه؟
- يمكنك استخدام المتغير المتقلب إذا كنت تريد القراءة والكتابة للمتغير الطويل والمزدوج تلقائيًا.
- يمكن استخدامه كطريقة بديلة لتحقيق التزامن في Java.
- سترى جميع سلاسل القارئ القيمة المحدثة للمتغير المتقلب بعد إكمال عملية الكتابة. إذا كنت لا تستخدم الكلمة الأساسية المتغيرة، فقد يرى مؤشر ترابط القارئ المختلف قيمًا مختلفة.
- يتم استخدامه لإبلاغ المترجم بأن عدة سلاسل رسائل ستصل إلى بيان معين. يمنع المترجم من القيام بأي إعادة ترتيب أو أي تحسين.
- إذا كنت لا تستخدم المترجم المتغير المتغير، فيمكنك إعادة ترتيب الكود، ويمكنك كتابة قيمة المتغير المتطاير في ذاكرة التخزين المؤقت بدلاً من القراءة من الذاكرة الرئيسية.
نقاط مهمة
- يمكنك استخدام الكلمة الأساسية المتقلبة مع المتغيرات. يعد استخدام الكلمات الأساسية المتقلبة مع الفئات والأساليب أمرًا غير قانوني.
- ويضمن أن قيمة المتغير المتطاير ستتم قراءتها دائمًا من الذاكرة الرئيسية، وليس من ذاكرة التخزين المؤقت لمؤشر الترابط المحلي.
- إذا قمت بتعريف المتغير على أنه متقلب، فإن القراءة والكتابة تعتبر ذرية
- فهو يقلل من خطر حدوث خطأ في تناسق الذاكرة.
- أي كتابة إلى متغير متغير في Java تحدد حدوثًا قبل العلاقة مع القراءات المتعاقبة لنفس المتغير.
- تكون المتغيرات المتقلبة مرئية دائمًا للخيوط الأخرى.
- قد يكون المتغير المتقلب الذي يعد مرجعًا للكائن خاليًا.
- عندما لا تتم مشاركة متغير بين سلاسل رسائل متعددة، فلن تحتاج إلى استخدام الكلمة الأساسية المتقلبة مع هذا المتغير.
الفرق بين المزامنة والكلمة الرئيسية المتقلبة
الكلمة الرئيسية المتغيرة ليست بديلاً عن الكلمة الرئيسية المتزامنة، ولكن يمكن استخدامها كبديل في حالات معينة. وهناك الفروق التالية وهي كما يلي:
الكلمة الرئيسية المتقلبة | الكلمة الأساسية للمزامنة |
---|---|
الكلمة الأساسية المتقلبة هي معدّل الحقل. | تقوم الكلمة الأساسية المتزامنة بتعديل كتل التعليمات البرمجية والأساليب. |
لا يمكن حظر الخيط للانتظار في حالة التقلب. | يمكن حظر المواضيع للانتظار في حالة المزامنة. |
يعمل على تحسين أداء الخيط. | تؤدي الأساليب المتزامنة إلى انخفاض أداء مؤشر الترابط. |
يقوم بمزامنة قيمة متغير واحد في كل مرة بين ذاكرة الخيط والذاكرة الرئيسية. | يقوم بمزامنة قيمة جميع المتغيرات بين ذاكرة الخيط والذاكرة الرئيسية. |
الحقول المتطايرة لا تخضع لتحسين برنامج التحويل البرمجي. | المزامنة تخضع لتحسين المترجم. |
مثال على الكلمات الرئيسية المتقلبة
في المثال التالي، قمنا بتعريف فئة تزيد من قيمة العداد. تحصل طريقة التشغيل () في VolatileThread.java على القيمة المحدثة والقيمة القديمة عندما يبدأ تنفيذ مؤشر الترابط. في الفئة الرئيسية، نحدد مصفوفة الخيط.
VolatileData.java
public class VolatileData { private volatile int counter = 0; public int getCounter() { return counter; } public void increaseCounter() { ++counter; //increases the value of counter by 1 } }
VolatileThread.java
VolatileThread.java public class VolatileThread extends Thread { private final VolatileData data; public VolatileThread(VolatileData data) { this.data = data; } @Override public void run() { int oldValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: Old value = ' + oldValue); data.increaseCounter(); int newValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: New value = ' + newValue); } }
VolatileMain.java
جافا عدد صحيح إلى السلسلة
public class VolatileMain { private final static int noOfThreads = 2; public static void main(String[] args) throws InterruptedException { VolatileData volatileData = new VolatileData(); //object of VolatileData class Thread[] threads = new Thread[noOfThreads]; //creating Thread array for(int i = 0; i <noofthreads; ++i) threads[i]="new" volatilethread(volatiledata); for(int i="0;" < noofthreads; threads[i].start(); starts all reader threads threads[i].join(); wait for } pre> <p> <strong>Output:</strong> </p> <pre> [Thread 9]: Old value = 0 [Thread 9]: New value = 1 [Thread 10]: Old value = 1 [Thread 10]: New value = 2 </pre> <hr></noofthreads;>