5

मैं एक विशिष्ट सेवा शुरू करने वाले सिस्टम के कुछ हिस्सों को सूचित करने के लिए एक बूलियन रखना चाहता हूं।सिंक्रनाइज़ ऑब्जेक्ट को सूचित करने से पहले थ्रेड द्वारा लॉक नहीं किया गया है सभी()

कुछ अजीब कारणों से मुझे त्रुटि java.lang.IllegalMonitorStateException: object not locked by thread before notifyAll() मिल रही है।

अजीब बात यह है कि अधिसूचना सभी() एक सिंक्रनाइज़ ब्लॉक के अंदर है जो उस ऑब्जेक्ट पर नियंत्रण लेता है जिसे मैं सूचित करता हूं सभी() चालू।

मेरी कक्षा इस तरह शुरू होता है:

public class MyService { 

    public static Boolean notifier = Boolean.valueOf(false); 

    @Override 
    public void start() { 
     synchronized (MyService.notifier) { 
      MyService.notifier = Boolean.valueOf(true); 
      MyService.notifier.notifyAll(); 
     } 
    } 

    @Override 
    public void stop() { 
     synchronized (MyService.notifier) { 
      MyService.notifier = Boolean.valueOf(false); 
      MyService.notifier.notifyAll(); 
     } 
    } 
    ... 
} 

मैं एक Android आवेदन पर काम कर रहा हूँ। मुझे नहीं लगता कि इसे किसी भी चीज़ को प्रभावित करना चाहिए, लेकिन मैं उस टिप्पणी के साथ इस सवाल का पूरक हूं कि जावा काम करने के तरीके को प्रभावित करता है।

अगर ऑब्जेक्ट सिंक्रनाइज़ किए गए ब्लॉक के अंदर लॉक हो तो मुझे अपवाद क्यों मिल रहा है?

+1

[इस SO प्रश्न] पर एक नज़र डालें [http://stackoverflow.com/questions/260337/why-does-synchronized-notifyall-result-in-a-illegalmonitorstateexception?rq=1) –

+3

क्योंकि मॉनिटर संबंधित है _object_ पर, _field_ पर नहीं। आप 'Boolean.FALSE' पर सिंक्रनाइज़ कर रहे हैं लेकिन' बूलियन.TRUE' (या इसके विपरीत) को सूचित करते हैं। –

+4

कहानी का नैतिक है; एक म्यूटेबल ऑब्जेक्ट को लॉक न करें, सुनिश्चित करें कि यह 'अंतिम' है, आपका कोड जितना जटिल होना चाहिए उससे कहीं अधिक जटिल है, लेकिन मैं यह सुझाव नहीं दे सकता कि आप इसके लिए क्या इंतजार कर रहे हैं इसे देखे बिना इसे प्रतिस्थापित करना है। (जैसा कि यह खड़ा है आप इसे सब हटा सकते हैं) मुझे संदेह है कि एक एक्जिक्यूटर्स सेवा है जिसका उपयोग आप करना चाहिए। –

उत्तर

17

लाइन वस्तु बाहर

MyService.notifier = Boolean.valueOf(true); 

स्वैप आप पर ताला लगा रहे हैं, यह एक नई वस्तु के लिए एक संदर्भ के साथ चर को ओवरराइट। तो जिस ब्लॉक को आपने ब्लॉक दर्ज करने पर लॉक हासिल किया है वह वही नहीं है जिसे आप notifyAll पर कॉल कर रहे हैं। सभी notifyAll जानता है कि यह उस ऑब्जेक्ट पर लॉक प्राप्त नहीं किया गया है जिस पर इसे कॉल किया जा रहा है, जो सिंक्रनाइज़ ब्लॉक दर्ज किए जाने के बाद बनाई गई नई वस्तु है।

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

+0

धन्यवाद। मैं उसके साथ अटक गया था। –

+1

@ जे-राउ: मदद करने में खुशी हुई। थोड़ी देर में हर कोई फंस जाता है, यह एक व्यावसायिक खतरा है। –