2012-11-26 16 views
5

निम्नलिखित पर विचार करें: ARIAN मेरे लिए झुके गया है:डेडलॉक प्रक्रिया कौन सा पहला लॉक करता है?

public class Deadlock { 
static class Friend{ 
    private final String name; 

    public Friend (String name){ 
     this.name = name; 
    } 

    public String getName(){ 
     return this.name; 
    } 


    public synchronized void bow(Friend bower){ 
     System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName()); 
     bower.bowBack(this); 
    } 
    public synchronized void bowBack(Friend bower) { 
     System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName()); 
    } 


} 

public static void main(String[] args) { 
    final Friend alf = new Friend("Alf"); 
    final Friend arian = new Friend("Arian"); 

    // Thread 1 
      new Thread(new Runnable() { 
     public void run(){ alf.bow(arian);}}).start(); 

    //Thread 2 
    new Thread(new Runnable() { 
     public void run(){ arian.bow(alf);}}).start(); 
} 

}

बाहर डाल

ALF है! एरियान: एएलएफ ने मुझे झुकाया है!

लॉक स्थिति .....

जब थ्रेड 1 रन, यह वस्तु दोस्त पर एक लॉक की आवश्यकता है। उस थ्रेड 2 के तुरंत बाद दूसरी ऑब्जेक्ट पर लॉक की आवश्यकता होती है। अब विधि धनुष थ्रेड 1 द्वारा लॉक है और इस प्रकार प्रिंट करता है "ALF: एरियन ने मुझे झुकाया है!"। थ्रेड 2 कैसे आता है धनुष और न ही * धनुष * दर्ज कर सकते हैं ??

सादर बी

उत्तर

5

याद रखिए synchronized तरीकों हमेशा this पर सिंक्रनाइज़ कर सकते हैं।

दो वस्तुएं हैं और इसलिए दो ताले हैं। alf.bow()alf एस लॉक प्राप्त करता है और arian.bow()arian एस प्राप्त करता है। लेकिन फिर bowback() दूसरे को हासिल करने का प्रयास करता है, जो तब होता है जब डेडलॉक होता है।

आप एक साझा ताला वस्तु पर सिंक्रनाइज़ करने के लिए चाहते हैं, आप कुछ इस तरह करना चाहिए:

class Friend { 
    private static final Object lock = new Object(); 

    public void bow(...) { 
    synchronized(lock) { 
     ... 
    } 
    } 

    public void bowback(...) { 
    synchronized(lock) { 
     ... 
    } 
    } 

} 

के बाद से lock एक स्थिर क्षेत्र में है तो इसका मतलब Friend के सभी उदाहरणों में एक ही ताला वस्तु का उपयोग, इसलिए डेडलॉक का कोई मौका नहीं है।

तुम भी वर्ग वस्तु synchronized(Friend.class) {...} पर सिंक्रनाइज़ कर सकते हैं, लेकिन आमतौर पर बाहर से दिखाई देने वस्तुओं पर सिंक्रनाइज़ कर एक अच्छा विचार नहीं है के रूप में कोई गारंटी नहीं कि कोड के किसी अन्य भाग ताला चोरी नहीं करता नहीं है।

+0

आपकी टिप्पणियों के लिए बहुत सारे धन्यवाद। –

3

सिंक्रनाइज़ेशन किसी ऑब्जेक्ट का उपयोग करके किया जाता है; धागे सिंक्रनाइज़ किए गए ब्लॉक में एक साथ प्रवेश कर सकते हैं अगर वे विभिन्न वस्तुओं के साथ सिंक्रनाइज़ होते हैं।

एक उदाहरण विधि में synchronized कीवर्ड का मतलब है कि ब्लॉक कि उदाहरण द्वारा सिंक्रनाइज़ है। चूंकि आप दो अलग-अलग ऑब्जेक्ट्स की bow विधि को कॉल कर रहे हैं, इसलिए कोई नियंत्रण नहीं है कि दोनों एक ही समय में इस तरह के फ़ंक्शन निष्पादित करते हैं।

कक्षा ऑब्जेक्ट द्वारा सिंक्रनाइज़ करें (या उस अंत में बनाए गए स्थिर अंतिम ऑब्जेक्ट का उपयोग करें)।

1

- आप 2 objects का इस्तेमाल किया है, और दोनों धागे यहाँ 2 अलग मॉनिटर ताले उपयोग कर रहे हैं।

- के रूप में दोनों धागे 2 different object पर ताला हो रही है, इसकी काफी स्पष्ट वस्तु 1 पर धागा 1 का ताला धागा 2 वस्तु 2 ताला लेने पर कोई प्रभाव नहीं पड़ता है।

- आप synchronized कीवर्ड जो एक वस्तु यहां लॉक की आवश्यकता का इस्तेमाल किया है, और आप अपने स्वयं के वस्तु ताले के साथ दोनों धागे प्रदान कर रहे हैं, तो सूत्र 2 धनुष दर्ज करें।

1

आपको एक सामान्य वस्तु को लॉक करने की आवश्यकता है।

public static void main(String[] args) { 
    final Object lock = new Object(); 
    final Friend alf = new Friend("Alf", lock); 
    final Friend arian = new Friend("Arian", lock); 
    ... 
} 


public void bow(Friend bower){ 
    synchronize(lock){ 
     System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName()); 
     bower.bowBack(this); 
    } 
} 
public void bowBack(Friend bower) { 
    synchronize(lock){ 
     System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName()); 
    } 
} 
संबंधित मुद्दे