2012-01-03 51 views
6

मैं आधिकारिक GAE documentation on transactions पढ़ रहा हूं और मुझे समझ में नहीं आता कि ConcurrentModificationException फेंक दिया गया है। उदाहरण जो मैं कॉपी-पेस्ट यहाँ हूँ में से एक मेंGAE में ConcurrentModificationException फेंक दिया गया है?

देखो:

int retries = 3; 
while (true) { 
    Transaction txn = datastore.beginTransaction(); 
    try { 
     Key boardKey = KeyFactory.createKey("MessageBoard", boardName); 
     Entity messageBoard = datastore.get(boardKey); 

     long count = (Long) messageBoard.getProperty("count"); 
     ++count; 
     messageBoard.setProperty("count", count); 
     datastore.put(messageBoard); 

     txn.commit(); 
     break; 
    } catch (ConcurrentModificationException e) { 
     if (retries == 0) { 
      throw e; 
     } 
     // Allow retry to occur 
     --retries; 
    } finally { 
     if (txn.isActive()) { 
      txn.rollback(); 
     } 
    } 
} 

अब, डेटा स्टोर (इस उदाहरण में) के लिए सभी लेखन एक सौदे के तहत लिपटे रहे हैं। तो ConcurrentModificationException क्यों फेंक दिया जाएगा?

क्या ऐसा होता है जब किसी अन्य कोड को लेनदेन में लपेटा नहीं जाता है, तो उसी इकाई को अद्यतन किया जाता है जिसे उपरोक्त कोड द्वारा संशोधित किया जा रहा है? अगर मैं सुनिश्चित करता हूं कि एक इकाई को अद्यतन करने वाला सभी कोड हमेशा लेनदेन में लपेटा जाता है, तो क्या यह गारंटी है कि मुझे ConcurrentModificationException नहीं मिलेगा?

उत्तर

1

मुझे GAE मेलिंग सूची पर उत्तर मिला।

मुझे GAE में लेन-देन कैसे काम करते हैं, इस बारे में एक गलत धारणा थी। मैंने कल्पना की थी कि एक लेनदेन शुरू करने से डेटास्टोर तक लेन-देन होने तक किसी भी समवर्ती अपडेट को लॉक कर दिया जाएगा। यह एक प्रदर्शन दुःस्वप्न होता क्योंकि सभी लेन-देन इस लेनदेन पर अवरुद्ध होंगे और मुझे खुशी है कि यह मामला नहीं है।

इसके बजाय, क्या होता है, पहला अपडेट जीतता है, और यदि बाद के अपडेट में टकराव का पता चला है, तो एक अपवाद फेंक दिया जाता है।

इससे पहले मुझे आश्चर्य हुआ, क्योंकि इसका मतलब है कि कई लेन-देन को पुनः प्रयास तर्क की आवश्यकता होगी। लेकिन यह "serializable अलगाव" स्तर के लिए PostgreSQL semantics के समान लगता है, हालांकि PostgreSQL में आपके पास व्यक्तिगत पंक्तियों और स्तंभों को लॉक करने का विकल्प भी है।

+0

उद्धरण के दूसरे अनुच्छेद से यह अलग कैसे है? – Kiril

+0

लिरिक, यह आपके द्वारा उद्धृत उद्धरण से बहुत अलग नहीं है। लेकिन उद्धरण के नीचे आपका सारांश मेरा से अलग है, और उत्तर में कुछ मान्यताओं और असंबंधित उद्धरण हैं। इसलिए, मैंने अपने भ्रम को स्पष्ट करते हुए एक नया जवाब दिया। इस खोज में भाग लेने के लिए धन्यवाद। – HRJ

+0

अच्छा, महत्वपूर्ण बात यह है कि आपके पास जवाब है:) ... – Kiril

0

यह आप क्या कर रहे हैं कि वे आप क्या सुझाव है कि लगता है ऐसा नहीं चाहिए: http://code.google.com/appengine/docs/java/datastore/transactions.html#Uses_for_Transactions

चेतावनी! उपर्युक्त नमूना सरलता के लिए केवल एक काउंटर को लेनदेन में वृद्धि दर्शाता है। यदि आपके ऐप में काउंटर हैं जो अक्सर अपडेट होते हैं, तो आपको उन्हें लेन-देन में वृद्धि नहीं करना चाहिए, या यहां तक ​​कि एक इकाई के भीतर भी नहीं। काउंटरों के साथ काम करने का सबसे अच्छा अभ्यास काउंटर-शेर्डिंग नामक तकनीक का उपयोग करना है।

शायद ऊपर चेतावनी लागू नहीं होता है, लेकिन उसके बाद यह मुद्दा आप देख रहे हैं में संकेत करने लगता है क्या इस प्रकार है: क्योंकि मूल्य के द्वारा अद्यतन किया जा सकता है

यह एक सौदे की आवश्यकता है इस कोड के बाद कोई अन्य उपयोगकर्ता ऑब्जेक्ट लाता है, लेकिन इससे पहले संशोधित ऑब्जेक्ट को बचाता है। लेनदेन के बिना, उपयोगकर्ता का अनुरोध दूसरे उपयोगकर्ता के अपडेट से पहले गिनती के मूल्य का उपयोग करता है, और सहेजने से नए मान को ओवरराइट किया जाता है। लेनदेन के साथ, एप्लिकेशन को अन्य उपयोगकर्ता के अपडेट के बारे में बताया जाता है। यदि लेनदेन के दौरान इकाई को अद्यतन किया जाता है, तो लेनदेन ConcurrentModificationException के साथ विफल रहता है। एप्लिकेशन नए डेटा का उपयोग करने के लिए लेनदेन दोहरा सकता है।

दूसरे शब्दों में: ऐसा लगता है कि कोई लेनदेन के बिना एक ही इकाई को अपडेट कर रहे हैं, उसी समय लेनदेन का उपयोग किए बिना आपकी इकाई को संशोधित कर रहा है।

नोट: अत्यंत दुर्लभ मामलों में, लेनदेन पूरी तरह से किया जाता है भले ही लेनदेन एक टाइमआउट या आंतरिक त्रुटि अपवाद देता है। इस कारण से, जब भी संभव हो लेनदेन idempotent बनाना सबसे अच्छा है।

एक निष्पक्ष चेतावनी: मैं पुस्तकालय से परिचित नहीं हूँ, लेकिन इसके बाद के संस्करण उद्धरण प्रलेखन दिखा नमूना लेन-देन (जो कि तुम क्या मूल प्रश्न में पोस्ट किया है के समान लगता है) से ले जाया गया।

+0

यह चेतावनी पूरी तरह से अलग कारण के लिए है: प्रदर्शन। लेनदेन के संदर्भ में, यह एक पूरी तरह से मान्य उदाहरण है। चेतावनी के बाद पैराग्राफ में – HRJ

+0

एचआरजे यह भी बताता है कि लेनदेन के दौरान इकाई को अद्यतन किया गया है, तो लेनदेन 'ConcurrentModificationException' के साथ विफल हो सकता है। मुझे लगता है कि इस मामले में यह हो रहा है। – Kiril

+0

प्रश्न का उत्तर देने का प्रयास करने के लिए धन्यवाद। मुझे पहले से ही पता है कि प्रलेखन में क्या है। मुझे धारणाओं के बिना एक जवाब चाहिए। – HRJ

संबंधित मुद्दे