2012-09-25 21 views
23

निम्नलिखित कोड JavaDoc of Condition से लिया जाता है एक रैत्रांत में एक शर्त पर प्रतीक्षा कर रहा: का एक उदाहरण परताला

class BoundedBuffer { 
    final Lock lock = new ReentrantLock(); 
    final Condition notFull = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 

    final Object[] items = new Object[100]; 
    int putptr, takeptr, count; 

    public void put(Object x) throws InterruptedException { 
    lock.lock(); 
    try { 
     while (count == items.length) 
     notFull.await(); 
     items[putptr] = x; 
     if (++putptr == items.length) putptr = 0; 
     ++count; 
     notEmpty.signal(); 
    } finally { 
     lock.unlock(); 
    } 
    } 

    public Object take() throws InterruptedException { 
    lock.lock(); 
    try { 
     while (count == 0) 
     notEmpty.await(); 
     Object x = items[takeptr]; 
     if (++takeptr == items.length) takeptr = 0; 
     --count; 
     notFull.signal(); 
     return x; 
    } finally { 
     lock.unlock(); 
    } 
    } 
} 

कल्पना कीजिए 2 सूत्र, उपभोक्ता और निर्माता, एक take का उपयोग कर, एक putBoundedBuffer

मान लीजिए कि उपभोक्ता पहले चला जाता है, take() जिसमें उन्होंने lock ताले और अब notEmpty.await(); पर लूप तक चलता है।

कैसे कर सकता है अब निर्माता संभवतः lock, जो पहले से ही उपभोक्ता द्वारा आयोजित किया जाता है ताला लगा अतीत put() विधि में मिल सकता है?

मुझे यहां क्या याद आ रही है? क्या lock "अस्थायी रूप से जारी किया गया है" जबकि थ्रेड इसकी स्थितियों में से किसी एक पर इंतजार कर रहा है? और ताला मतलब के पुनर्वित्त क्या है, बिल्कुल?

+2

मैं के बारे में था पर 10-15% से कम है दो के साथ बिल्कुल वैसा ही सवाल पूछते हैं JavaDoc पर बिल्कुल वही उदाहरण :) मुझे समय खोने से बचाया। – Bren

उत्तर

23

Lock और synchronized थ्रेड को प्रतीक्षा करते समय लॉक छोड़ने की अनुमति दें और दूसरा थ्रेड लॉक प्राप्त कर सकता है। प्रतीक्षा रोकने के लिए, एक थ्रेड को लॉक फिर से हासिल करना होगा।

नोट: वे इसे पूरी तरह से रिलीज़ नहीं करते हैं और यदि आप एक स्टैक ट्रेस लेते हैं तो आपके पास कई धागे हो सकते हैं जो एक बार में लॉक धारण करते हैं, लेकिन उनमें से अधिकतर चल रहे होंगे (शेष अवरुद्ध हो जाएंगे)

Condition.await()

इस स्थिति के साथ जुड़े ताला से atomically जारी की है और मौजूदा धागा धागा शेड्यूलिंग प्रयोजनों के लिए विकलांग हो जाता है और निष्क्रिय झूठ जब तक चार चीजों में से एक होता है:

  • कुछ अन्य धागे इस स्थिति के लिए सिग्नल() विधि का आह्वान करते हैं और वर्तमान थ्रेड को थ्रेड के रूप में चुना जाता है; या
  • कुछ अन्य धागे इस स्थिति के लिए सिग्नलअल() विधि का आह्वान करते हैं; या
  • कुछ अन्य धागे वर्तमान धागे को बाधित करते हैं, और थ्रेड निलंबन के बाधा को समर्थित किया जाता है; या
  • एक "नकली wakeupup" होता है।

सभी मामलों में, इस विधि से पहले इस थ्रेड को वापस कर सकते हैं इस स्थिति से जुड़े लॉक को पुनः प्राप्त करना होगा। जब थ्रेड लौटाता है तो यह लॉक

+0

क्या आप प्रासंगिक दस्तावेज का लिंक प्रदान कर सकते हैं? – vektor

+1

@ पीटर Lawrey '(बाकी इंतजार करेंगे)' या अवरुद्ध? मुझे लगता है कि वे ब्लॉक राज्य में होना चाहिए? – UnKnown

+0

क्या आप इस वाक्य को समझा सकते हैं: "लॉक और सिंक्रनाइज़ दोनों अस्थायी रूप से दूसरों को प्रतीक्षा करते समय लॉक प्राप्त करने की अनुमति देते हैं।" यह मुझे समझ में नहीं आता है। – Chin

5

जहां तक ​​पुन: प्रवेश होता है, इसका मतलब है कि एक थ्रेड जो एक निश्चित लॉक रखता है, फिर से उसी लॉक को पुनः प्राप्त कर सकता है। यदि ऐसा नहीं था, तो synchronized विधि एक ही ऑब्जेक्ट की synchronized विधि को कॉल करने में सक्षम नहीं होगी।

पुन: प्रवेश आपकी समस्या की समझ में शामिल नहीं है।

+0

बिल्कुल। कभी-कभी शब्द "रिकर्सिव लॉक" का उपयोग पुनर्विक्रेता ताले के लिए किया जाता है, [विकिपीडिया] (https://en.wikipedia.org/wiki/Reentrant_mutex) देखें। – TheOperator

-2

मैं एक की निगरानी के साथ नीचे दिए गए कोड का परीक्षण किया और नीचे हमेशा बेहतर प्रदर्शन करती है - 2 कोर मशीन पर परीक्षण किया गया, स्थिति प्रदर्शन औसत

final Object sync = new Object(); 
    AtomicInteger add=new AtomicInteger(); 
    AtomicInteger remove=new AtomicInteger(); 
    final Object[] items = new Object[1]; 
    int putptr, takeptr, count;   

public void add(Object x) throws InterruptedException { 
     add.incrementAndGet(); 

    synchronized (sync) { 

     while (count == items.length) 
     sync.wait(); 
     items[putptr] = x; 
     if (++putptr == items.length) putptr = 0; 
     ++count; 
     sync.notify(); 
     } 
    } 

    public Object remove() throws InterruptedException { 
     remove.incrementAndGet(); 

    synchronized (sync) { 

     while (count == 0) 
     sync.wait(); 
     Object x = items[takeptr]; 
     if (++takeptr == items.length) takeptr = 0; 
     --count; 
     sync.notify(); 
     return x; 

     } 
    } 


    public static void main(String[] args) { 
    final BoundedBuffer bf=new BoundedBuffer(); 

    Thread put =new Thread(){ 
     public void run(){ 
     try { 
      while(true) 
      bf.add(new Object()); 
     } catch (InterruptedException e) { 

     } 
     } 

    }; 
    put.start(); 

    Thread take= new Thread(){ 
     public void run(){ 
     try { 
     while(true) 
      bf.remove(); 
     } catch (InterruptedException e) { 

     } 
     } 

    }; 
    take.start(); 

    try { 
     Thread.sleep(1000L); 
     put.interrupt(); 
     take.interrupt(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 


    System.out.println("add:"+bf.add); 
    System.out.println("remove:"+bf.remove); 
संबंधित मुद्दे