java - ArrayBlockingQueue में, क्यों अंतिम सदस्य फ़ील्ड को स्थानीय अंतिम चर में कॉपी करें?




multithreading optimization (2)

यह एक चरम अनुकूलन है, कक्षा के लेखक डौग ली, का उपयोग करना पसंद करते हैं। इस सटीक विषय के बारे में कोर-libs-dev मेलिंग सूची पर हाल के धागे पर एक पोस्ट है जो आपके प्रश्न का बहुत अच्छा जवाब देता है।

पद से:

... स्थानीय लोगों को कॉपी करने से सबसे छोटा बाइटकोड उत्पन्न होता है, और निम्न-स्तरीय कोड के लिए यह कोड लिखना अच्छा होता है जो मशीन के करीब है

ArrayBlockingQueue , लॉक की आवश्यकता वाले सभी विधियों को lock() से पहले स्थानीय final चर में कॉपी करें।

public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            insert(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

क्या इसकी प्रतिलिपि बनाने का कोई कारण है। स्थानीय चर lock पर lock जब यह क्षेत्र होगा। lock final ?

इसके अतिरिक्त, यह इस पर अभिनय करने से पहले E[] की एक स्थानीय प्रति का भी उपयोग करता है:

private E extract() {
    final E[] items = this.items;
    E x = items[takeIndex];
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal();
    return x;
}

क्या अंतिम फ़ील्ड को स्थानीय अंतिम चर में कॉपी करने का कोई कारण है?


यह धागा कुछ जवाब देता है। पदार्थ में:

  • संकलक आसानी से साबित नहीं कर सकता कि एक अंतिम क्षेत्र किसी विधि के भीतर नहीं बदलता है (प्रतिबिंब / क्रमबद्धता आदि के कारण)
  • अधिकांश वर्तमान कंपाइलर्स वास्तव में कोशिश नहीं करते हैं और इसलिए इसे उपयोग किए जाने पर अंतिम फ़ील्ड को फिर से लोड करना होगा जो कैश मिस या पेज गलती का कारण बन सकता है
  • स्थानीय चर में इसे संग्रहीत करने से JVM केवल एक लोड करने के लिए मजबूर करता है




local-variables