2012-02-18 17 views
16

पढ़ना प्रभावी जावा, लेखक किक्यों हॉटस्पॉट hoisting का उपयोग कर निम्नलिखित अनुकूलित करेगा?

while(!done) i++; 

if (!done) { 
    while(true) i++ 
} 

में हॉटस्पॉट द्वारा अनुकूलित किया जा सकता है मैं बहुत इसके बारे में उलझन में हूँ उल्लेख किया है। किया गया है औपचारिक रूप से एक स्थिर नहीं है, क्यों संकलक इस तरह अनुकूलित कर सकते हैं?

उत्तर

20

लेखक मानते हैं कि परिवर्तनीय done एक स्थानीय चर है, जिसमें जावा मेमोरी मॉडल में सिंक्रनाइज़ेशन प्राइमेटिव के बिना अन्य धागे के मूल्य को बेनकाब करने के लिए कोई आवश्यकता नहीं है। या एक और तरीका कहा: done का मूल्य यहां दिखाए गए किसी भी अन्य कोड से बदला या देखा नहीं जाएगा।

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

इस तरह के एक सरणी की लंबाई के रूप में भी और अधिक जटिल भाव में काम करता है,:

int[] array = new int[10000]; 
for (int i = 0; i < array.length; ++i) { 
    array[i] = Random.nextInt(); 
} 

इस मामले में, भोली कार्यान्वयन सरणी की लंबाई 10,000 गुना का मूल्यांकन होता है, लेकिन जब से चर सरणी है कभी नहीं सौंपा और सरणी कभी नहीं बदलेगा की लंबाई, मूल्यांकन बदल सकते हैं:

int[] array = new int[10000]; 
for (int i = 0, $l = array.length; i < $l; ++i) { 
    array[i] = Random.nextInt(); 
} 

अन्य अनुकूलन भी यहाँ उत्थापन से संबंधित नहीं लागू होते हैं।

उम्मीद है कि मदद करता है।

+0

मुझे यह नहीं मिला है, अगर लूप समाप्त हो जाए, तो स्थिति हमेशा सच होती है? –

+2

मेरा मानना ​​है कि ईजे के बिंदु के लेखक यह है कि क्योंकि जेआईटी कंपाइलर * इस तरह अनुकूलित कर सकता है, एक प्रोग्रामर को एक अलग थ्रेड से 'किए गए' के ​​मूल्य पर निर्भर नहीं होना चाहिए। यह संभव है कि जेआईटी कंपाइलर इस निर्माण के लिए कोड को अनुकूलित कर सके और फिर लूप वास्तव में कभी समाप्त नहीं होगा। – ahawtho

+4

यह अनुकूलन तब भी हो सकता है जब 'किया' एक उदाहरण या वर्ग चर है, जब तक यह अस्थिर नहीं है। – assylias

0

यदि आप थोड़ी देर में System.out.println("i = " + i); जोड़ते हैं। उछाल काम नहीं करेगा, जिसका अर्थ है कि कार्यक्रम अपेक्षित रूप से बंद हो जाता है। Println विधि थ्रेड सुरक्षित है ताकि जेवीएम कोड सेगमेंट को अनुकूलित नहीं कर सके?

0
public class StopThread { 
private static boolean stopRequested; 

private static synchronized void requestStop() { 
    stopRequested = true; 
} 

private static synchronized boolean stopRequested() { 
    return stopRequested; 
} 

public static void main(String[] args) 
       throws InterruptedException { 
    Thread backgroundThread = new Thread(new Runnable() { 
     public void run() { 
      int i = 0; 
      while (!stopRequested()) 
       i++; 
     } 
    }); 
    backgroundThread.start(); 
    TimeUnit.SECONDS.sleep(1); 
    requestStop(); 
} 
} 

ऊपर कोड प्रभावी कोड में सही है, यह बराबर है कि volatile का उपयोग stopRequested को सजाने के लिए है।

private static boolean stopRequested() { 
    return stopRequested; 
} 

इस विधि को छोड़ देते हैं, तो synchronized कीवर्ड, इस कार्यक्रम अच्छी तरह से काम नहीं कर रहा।
मुझे लगता है कि यह परिवर्तन उछाल का कारण बनता है जब विधि synchronized कीवर्ड को छोड़ देती है।

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