2013-06-18 5 views
7

हाय जावा प्रभावी संस्करण से स्निपेट नीचे है। यहां लेखक का दावा है कि निम्नलिखित कोड का कोड 25% तेज है जिसमें आप परिणाम चर का उपयोग नहीं करते हैं। "यह वैरिएबल क्या करता है यह पुस्तक यह सुनिश्चित करने के लिए है कि क्षेत्र सामान्य मामले में केवल एक बार पढ़ा जाता है जहां यह पहले ही प्रारंभ हो चुका है।" । मुझे यह समझने में सक्षम नहीं है कि मूल्य को प्रारंभ करने के बाद यह कोड तेज क्यों होगा, यदि हम स्थानीय चर परिणाम का उपयोग नहीं करते हैं। किसी भी मामले में प्रारंभिकरण के बाद आपके पास केवल एक अस्थिर पढ़ा जाएगा चाहे आप स्थानीय चर परिणाम का उपयोग करें या नहीं।जोशुआ ब्लॉच प्रभावी जावा उदाहरण में डबल चेक लॉकिंग 25% तेज है उदाहरण

// Double-check idiom for lazy initialization of instance fields 
private volatile FieldType field; 

FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
      result = field; 
      if (result == null) // Second check (with locking) 
       field = result = computeFieldValue(); 
     } 
    } 
    return result; 
} 
+1

उम, क्या यह पहला संस्करण है? दो साल के लिए दो बार चेक लॉकिंग को निराश कर दिया गया है – fge

+0

और इसका कारण यह है: http://stackoverflow.com/questions/4926681/why-is-double-checked-locking-broken-in-java?rq=1 – Lenymm

+4

@fge : ज़रुरी नहीं। जावा 5 के बाद से, यह वास्तव में एक ठीक पैटर्न है: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html –

उत्तर

6

एक बार field initialised किया गया है, कोड या तो है:

if (field == null) {...} 
return field; 

या: जबकि दो बार

result = field; 
if (result == null) {...} 
return result; 

पहला मामला आप अस्थिर चर पढ़ें दूसरे में आप केवल इसे एक बार पढ़ें। यद्यपि अस्थिर पढ़ने बहुत तेज़ होते हैं, वे स्थानीय चर से पढ़ने से थोड़ा धीमा हो सकते हैं (मुझे नहीं पता कि यह 25% है)।

नोट्स:

  • अस्थिर पढ़ता के रूप में सस्ते के रूप में सामान्य हाल प्रोसेसर (कम से कम 86)/JVMs, यानी वहां कोई अंतर नहीं है पर पढ़ता है।
  • हालांकि कंपाइलर बिना अस्थिर के कोड को बेहतर अनुकूलित कर सकता है ताकि आप बेहतर संकलित कोड से दक्षता प्राप्त कर सकें।
  • कुछ नैनोसेकंड का 25% अभी भी बहुत कुछ नहीं है।
  • यह है एक मानक मुहावरा है कि आप java.util.concurrent पैकेज के कई वर्गों में पा सकते हैं - उदाहरण के this method in ThreadPoolExecutor के लिए देख (देखते हैं उनमें से कई)
+0

ठीक है तो इसका मतलब है कि "वापसी क्षेत्र" भी एक अस्थिर पढ़ने के लिए गठित होता है (प्रदत्त फ़ील्ड अस्थिर है) – veritas

+0

@veritas हां यह करता है - यदि आप बाइटकोड की जांच करते हैं तो आप देखेंगे कि इसे वापस आने से पहले लोड किया गया है। – assylias

+0

ठीक है बहुत बहुत धन्यवाद @assylias – veritas

0

सबसे आमंत्रण में एक स्थानीय चर का उपयोग कर, बिना हमारे पास प्रभावी रूप से

if(field!=null) // true 
    return field; 

तो वहाँ दो वाष्पशील पढ़ता है जो धीमी गति से एक अस्थिर पढ़ा है कर रहे हैं।

असल में जेवीएम दो अस्थिर पढ़ने को एक अस्थिर पढ़ने में विलय कर सकता है और अभी भी जेएमएम के अनुरूप है। लेकिन हम उम्मीद करते हैं कि जेवीएम एक अच्छा विश्वास करने के लिए हर बार एक अच्छा विश्वास अस्थिर पढ़ेगा, स्मार्टस बनने के लिए और किसी भी अस्थिर पढ़ने को अनुकूलित करने का प्रयास करें। इस कोड पर विचार करें

volatile boolean ready; 

do{}while(!ready); // busy wait 

हम उम्मीद करते हैं कि जेवीएम वास्तव में बार-बार चर को लोड करेगा।

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