2015-11-12 7 views
6

में समझौता विदेशी तरीकों मैं जे बलोच के प्रभावी जावा पढ़ रहा हूँ और अब मैं विदेशी तरीकों के बारे में खंड पर हूँ।जावा संगामिति

मैं जावा संगामिति और नुकसान वे कर सकता है में विदेशी तरीकों को समझने के लिए कोशिश कर रहा हूँ। जैसा कि उन्होंने कहा, हम मूल रूप से नहीं जानते कि विदेशी तरीके क्या कर सकती हैं और हम डेडलॉकिंग समाप्त कर सकते हैं। मैं इस तरह के एक deadlocking व्यवहार निम्नलिखित सरल अनुप्रयोग लिख पुन: पेश करने की कोशिश की (विदेशी विधि सादगी के लिए एक ही कक्षा में है):

public class App { 
    private static StringBuffer lines = new StringBuffer(); 

    public static void modifyLines(){ 
     System.out.println("Invocation modifyLines() started by " + Thread.currentThread().getName()); 
     synchronized (lines) { 
      System.out.println("Entering modifyLines() synchronized " + Thread.currentThread().getName()); 
      lines.append("Modified"); 
     } 
    } 

    public static void main(String[] args) throws InterruptedException { 
     synchronized (lines) { 
      System.out.println("Entering main() synchronized by " + Thread.currentThread().getName()); 
      alienMethod(); 
     } 
    } 

    public static void alienMethod(){ 
     ExecutorService es = Executors.newSingleThreadExecutor(); 
     es.submit(new Runnable() { 
      @Override 
      public void run() { 
       modifyLines(); 
      } 
     }); 
     es.shutdown(); 
    } 
} 

मैं एक गतिरोध की उम्मीद जगह लेने के लिए और है कि धागा alienMethod() को फोन करके पैदा की होगा modifyLines() के भीतर सिंक्रनाइज़ ब्लॉक कभी दर्ज न करें।

Entering main() synchronized by main 
Invocation modifyLines() started by pool-1-thread-1 
Entering modifyLines() synchronized pool-1-thread-1 

गतिरोध नहीं हुआ इसका मतलब है: लेकिन कार्यक्रम निम्नलिखित प्रिंट करता है। क्यूं कर? विदेशी विधि उदाहरण के साथ क्या गलत है?

+2

विषय प्रभावी जावा, 2 एड में संगामिति के बारे में आइटम नहीं है। ब्रायन गोएट्ज़ द्वारा "अभ्यास में जावा कंसुरेंसी इन प्रैक्टिस" में अधिक व्यापक रूप से शामिल हैं। – scottb

उत्तर

3

आपका alienMethod() तक प्रस्तुत कार्य समाप्त हो गया है इंतजार नहीं करता है। आप इसके लिए इंतजार करना है, तो आप एक गतिरोध होगा:

public static void alienMethod() throws InterruptedException{ 
    ExecutorService es = Executors.newSingleThreadExecutor(); 
    es.submit(new Runnable() { 
     @Override 
     public void run() { 
      modifyLines(); 
     } 
    }); 
    es.shutdown(); 
    es.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); 
} 
+0

दरअसल, आप सही हैं। कोशिश की और एक डेडलॉक मिला। –

3

यह एक बहुत पुरानी सवाल है और इसका जवाब भी स्वीकार किया जाता है, लेकिन मैं इस पुराने कब्र खुदाई करने के लिए समय लगा, क्योंकि मुझे लगता है कि इस सवाल का जवाब पूरी तरह से सही नहीं है था और गुमराह कर सकता है।

मुझे पहले हाइलाइट करना शुरू करें कि उत्तर कैसे टूटा हुआ है - यदि आप es.awaitTermination(2, TimeUnit.SECONDS); के साथ चलते हैं तो आपको डेडलॉक नहीं मिलेगा, क्योंकि दिए गए कोड में कभी डेडलॉक स्थिति नहीं थी। गतिरोध उत्पन्न होती है आप 2 धागे एक दूसरे के होने के लिये आप कम से कम 2 ताले और 2 धागे के लिए होता है आम तौर पर एक गतिरोध के लिए, एक ताला जारी करने के लिए के लिए इंतजार है, जब। सुझाव दिया जवाब के अनुसार, क्या हो रहा था कि मुख्य थ्रेड awaitTermination का उपयोग करने और मुख्य थ्रेड के बाद से Long.MAX_VALUE साथ लॉक कर रहा है तो नया धागा मुख्य थ्रेड विज्ञप्ति जब तक लॉक "प्रतीक्षा" था, अब इस प्रतीक्षा अवधि भी था आयोजित किया गया था विशाल तो यह एक डेडलॉक की तरह लग रहा था, लेकिन असल में यह डेडलॉक की बजाय "प्रतीक्षा" था, और डेडलॉक को हल करने के लिए डेडलॉक और प्रतीक्षा में एक अंतर है, आपको अपना लॉकिंग कोड समायोजित करना होगा।

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

अब, नीचे प्रदर्शित करने के लिए एक उदाहरण कोड है (* "*****" * के साथ चिह्नित कोड टिप्पणियां पढ़ें, यह दिखाता है कि क्लाइंट विधि क्या कर रही है, इस पर निर्भर करता है कि एक डेडलॉक हो सकता है या एक डेडलॉक नहीं हो सकता है; यहाँ आप गतिरोध और इंतजार कर नहीं, मैं किसी भी प्रतीक्षा कोड का उपयोग नहीं किया है।

SetObserver।जावा:

public interface SetObserver { 
    void added(MyClass mc, SetObserver sc); 
} 

MyClass.java:

import java.util.concurrent.*; 

public class MyClass { 

    static Object o1 = new Object(); 

    public void test1(){ 
     synchronized(o1){ 
      System.out.println("test1"); 
     } 
    } 

    public void test3(SetObserver sc) throws InterruptedException{ 
     synchronized(o1){ 
      for (int i = 0; i < 100; i++) { 
       System.out.print("test3 >>" + i); 
       sc.added(this, sc); 
       synchronized(sc){ 
        System.out.println("<<"); 
       } 
      } 
     } 
    } 

    public static void main(String[] args) throws InterruptedException { 
     MyClass mc = new MyClass(); 
     mc.test3(new SetObserver() { 

      @Override 
      public void added(final MyClass mc, final SetObserver sc) { 
       // ***** This will not cause deadlock because it doesn't spawn a new thread, even though it synchronize on same object. ***** 
       /*synchronized(sc){ 
        mc.test1(); 
       }*/ 

       // ***** This causes a deadlock because it spawns a new thread, so it will cause lock contention among threads. ***** 
       ExecutorService xc = Executors.newFixedThreadPool(1); 
       xc.execute(new Runnable() { 

        @Override 
        public void run() { 
         synchronized(sc){ 
          System.out.println("Calling test1"); 
          mc.test1(); 
         } 
        } 
       }); 
       xc.shutdown(); 
      } 
     }); 
    } 
} 
+2

बहुत उपयोगी जवाब! धन्यवाद। – zhfkt

+0

@zhfkt जानना खुशी हुई, आपकी प्रतिक्रिया के लिए धन्यवाद। – hagrawal

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