JavaRush /جاوا بلاگ /Random-UR /دو تکرار کرنے والوں کی کہانی: جاوا میں مسابقتی ترمیم کی ح...

دو تکرار کرنے والوں کی کہانی: جاوا میں مسابقتی ترمیم کی حکمت عملی

گروپ میں شائع ہوا۔
نوٹ کے مصنف گرزیگورز میرک ہیں، جو کراکو (پولینڈ) سے ایک سافٹ ویئر ڈویلپر ہیں۔ اس نے تقریباً 6 سال پہلے جاوا میں ترقی کرنا شروع کی، جب وہ ابھی یونیورسٹی میں تھا، اور اس وقت سے وہ اس علاقے میں اپنی صلاحیتوں کو انتھک طریقے سے چمکا رہا ہے۔ وہ خاص طور پر JVM کی کارکردگی اور اصلاح میں دلچسپی رکھتا ہے، جس کے بارے میں وہ بنیادی طور پر اپنے بلاگ پر لکھتے ہیں ۔
دو تکرار کرنے والوں کی کہانی: جاوا میں مسابقتی تبدیلی کی حکمت عملی - 1
جاوا انٹرویو کے کچھ مشہور سوالات میں شامل ہیں: فیل فاسٹ اور فیل سیف تکرار کرنے والوں میں کیا فرق ہے؟ اس کا سب سے آسان جواب یہ ہے: ایک ناکام-تیز تکرار کنندہ ایک ConcurrentModificationException پھینکتا ہے اگر تکرار کے دوران مجموعہ تبدیل ہوتا ہے، لیکن ناکام-محفوظ تکرار کرنے والا ایسا نہیں کرتا ہے۔ اگرچہ یہ کافی معنی خیز لگتا ہے، لیکن یہ ابھی تک واضح نہیں ہے کہ انٹرویو لینے والے کا فیل سیف سے کیا مطلب ہے؟ جاوا زبان کی تصریحات تکرار کرنے والوں کے سلسلے میں اس اصطلاح کی وضاحت نہیں کرتی ہیں۔ تاہم، چار مسابقتی ترمیمی حکمت عملییں ہیں۔

مسابقتی ترمیم

پہلے، آئیے اس بات کی وضاحت کرتے ہیں کہ مسابقتی (یا متوازی) ترمیم کیا ہے۔ ہم کہتے ہیں کہ ہمارے پاس ایک مجموعہ ہے اور جب تکرار کرنے والا فعال ہوتا ہے، تو کچھ تبدیلیاں آتی ہیں جو اس تکرار کرنے والے سے نہیں آتیں۔ اس صورت میں، ہم ایک مسابقتی ترمیم حاصل کرتے ہیں. میں آپ کو ایک سادہ سی مثال دیتا ہوں: ہم کہتے ہیں کہ ہمارے پاس کئی تھریڈز ہیں۔ پہلا دھاگہ دہراتا ہے، اور دوسرا تھریڈ اسی مجموعہ سے عناصر کو داخل کرتا ہے یا ہٹاتا ہے۔ تاہم، ہم سنگل تھریڈڈ ماحول میں چلتے وقت ایک ConcurrentModificationException حاصل کر سکتے ہیں:
List<String> cities = new ArrayList<>();
cities.add(Warsaw);
cities.add(Prague);
cities.add(Budapest);

Iterator<String> cityIterator = cities.iterator();
cityIterator.next();
cities.remove(1);
cityIterator.next(); // генерирует ConcurrentModificationException

فیل فاسٹ

مذکورہ کوڈ کا ٹکڑا فیل فاسٹ ایٹریٹر کی ایک مثال ہے۔ جیسا کہ آپ دیکھ سکتے ہیں، ایک ConcurrentModificationException اس وقت پھینکا گیا جب iterator سے دوسرا عنصر بازیافت کرنے کی کوشش کی گئی ۔ ایک تکرار کنندہ کو کیسے پتہ چلتا ہے کہ مجموعہ میں ترمیم کے بعد سے اسے بنایا گیا ہے؟ مثال کے طور پر، مجموعہ میں تاریخ/وقت کی مہر ہو سکتی ہے، کہئے lastModified ۔ ایٹریٹر بناتے وقت، آپ کو اس فیلڈ کو کاپی کرنا چاہیے اور اسے ایٹریٹر آبجیکٹ میں اسٹور کرنا چاہیے۔ پھر، ہر بار جب آپ next() طریقہ کو کال کریں گے ، تو آپ کلیکشن کی آخری ترمیم شدہ قدر کا موازنہ دوبارہ کرنے والے کی کاپی کے ساتھ کریں گے۔ بالکل اسی طرح کا طریقہ استعمال کیا جاتا ہے، مثال کے طور پر، ArrayList کلاس کے نفاذ میں ۔ اس میں ایک مثال متغیر modCount ہے جو فہرست میں ترمیم کی گئی تعداد کو ذخیرہ کرتا ہے:
final void checkForComodification() {
   if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}
یہ نوٹ کرنا ضروری ہے کہ فیل فاسٹ تکرار کرنے والے بہترین نسل کی بنیاد پر کام کرتے ہیں، اس کا مطلب یہ ہے کہ اس بات کی کوئی گارنٹی نہیں ہے کہ ہم آہنگی ترمیم کی صورت میں ایک ConcurrentModificationException پھینک دیا جائے گا۔ لہذا آپ کو ان پر بھروسہ نہیں کرنا چاہئے - بلکہ، انہیں غلطیوں کا پتہ لگانے کے لئے استعمال کیا جانا چاہئے۔ زیادہ تر نان کنکرنٹ مجموعے فیل فاسٹ ایٹریٹر فراہم کرتے ہیں۔

کمزور مستقل مزاجی

java.util.concurrent پیکیج میں زیادہ تر سمورتی مجموعے (جیسے ConcurrentHashMap اور سب سے زیادہ قطار ) کمزور طور پر مسلسل تکرار کرنے والے فراہم کرتے ہیں۔ اس اصطلاح کے معنی دستاویزات میں بہت اچھی طرح سے بیان کیے گئے ہیں :
  • ان پر دوسرے آپریشنز کے ساتھ ساتھ عمل کیا جا سکتا ہے۔
  • وہ کبھی بھی ConcurrentModificationException نہیں پھینکتے ہیں۔
  • وہ اس وقت موجودہ عناصر کو عبور کرنے کی ضمانت دیتے ہیں جب تکرار کرنے والا بالکل ایک بار بنایا گیا تھا، اور بعد میں ہونے والی ترمیمات کی عکاسی کر سکتے ہیں (لیکن اس کی ضرورت نہیں ہے)۔

سنیپ شاٹ

اس حکمت عملی کے ساتھ، تکرار کنندہ اس کی تخلیق کے وقت مجموعہ کی حالت سے منسلک ہوتا ہے - یہ مجموعہ کا ایک سنیپ شاٹ ہے۔ اصل مجموعہ میں کی گئی کسی بھی تبدیلی کا نتیجہ بنیادی ڈیٹا ڈھانچے کا ایک نیا ورژن بنتا ہے۔ یہ ہمارے اسنیپ شاٹ کو بغیر کسی تبدیلی کے چھوڑ دیتا ہے، لہذا یہ اس مجموعہ میں ہونے والی تبدیلیوں کی عکاسی نہیں کرتا ہے جو تکرار کرنے والے کے بنائے جانے کے بعد ہوئی تھی۔ یہ اچھی پرانی کاپی آن رائٹ (COW) تکنیک ہے ۔ یہ سمورتی ترمیم کے مسئلے کو مکمل طور پر حل کرتا ہے، لہذا اس نقطہ نظر کے ساتھ ایک ConcurrentModificationException پیدا نہیں ہوتا ہے۔ مزید برآں، تکرار کرنے والے عناصر کو تبدیل کرنے والی کارروائیوں کی حمایت نہیں کرتے ہیں۔ کاپی پر لکھنے کے مجموعے استعمال کرنے کے لیے بہت مہنگے ہوتے ہیں، لیکن اگر تبدیلیاں تکرار کرنے والے ٹراورسلز کے مقابلے میں بہت کم ہوتی ہیں تو ان کو استعمال کرنا سمجھ میں آتا ہے۔ CopyOnWriteArrayList اور CopyOnWriteArraySet کلاسز کی مثالیں ہیں ۔

غیر متعینہ سلوک

آپ کو میراثی جمع کرنے کی اقسام جیسے کہ Vector اور Hashtable میں غیر متعینہ رویے کا سامنا ہو سکتا ہے ۔ دونوں کے پاس معیاری فیل فاسٹ تکرار کرنے والے ہیں، لیکن اس کے علاوہ، وہ شماری انٹرفیس کے نفاذ کے استعمال کی اجازت دیتے ہیں ، اور وہ نہیں جانتے کہ ہم آہنگی میں ترمیم کی صورت میں کیسے برتاؤ کرنا ہے۔ آپ کو کچھ عناصر کا بار بار یا غائب ہونے، یا یہاں تک کہ کچھ عجیب مستثنیات کا سامنا کرنا پڑ سکتا ہے۔ ان کے ساتھ نہ کھیلنا بہتر ہے!
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION