2011-08-13 11 views
10

की कल्पना किसी को किसी पूर्णांक लौटने के लिए एक विधि सिंक्रनाइज़ करता है:क्या जावा अनावश्यक सिंक्रनाइज़ बयान को हटा/अनुकूलित करता है?

int whatever = 33; 
... 

public synchronized int getWathever() { 
    return this.whatever; 
} 

हम जावा चश्मा कि ints atomically संशोधित कर रहे हैं से जानते हैं। इसलिए, synchronized कथन आवश्यक नहीं है।

क्या कंपेलर इसे हटा/अनुकूलित करेंगे?

+2

संदिग्ध। यदि आप (प्रोग्रामर) इसे अनावश्यक मानते हैं तो इसे कोड में निर्दिष्ट क्यों करें? – Hyperbole

+2

मैं नहीं करता, लेकिन मान लें कि मैं तीसरे पक्ष के कोड या कोड पर निर्भर करता हूं, मैंने खुद को नहीं लिखा था। – JVerstry

उत्तर

7

नहीं हो रही द्वारा यह सुनिश्चित करने के लिए सबसे आसान है, कि संभव नहीं है के दौरान किसी अन्य धागा द्वारा आयोजित नहीं किया गया है। यदि संकलक और JVM ऐसा करने के लिए थे, तो यह संभावना है कि जावा प्रोग्रामिंग भाषा मेमोरी मॉडल द्वारा निर्धारित बाधाओं का उल्लंघन किया जाएगा।

अधिक विशेष रूप से, synchronization order जावा भाषा विशिष्टता में वर्णित आदेश का उल्लंघन किया जाएगा। यदि कोई कंपाइलर या JVM * किसी भी "अवांछित" सिंक्रनाइज़ेशन को हटाना था, तो किसी और ऑप्टिमाइज़ेशन को सिंक्रनाइज़ेशन ऑर्डर (और पहले-पहले) रिश्ते पर डेवलपर द्वारा रखी गई किसी भी धारणा का उल्लंघन करना होगा। आपके विशिष्ट मामले में, पूर्णांक को कोई भी लिखना पढ़ने से पहले, एक कंपाइलर/जेवीएम में जावा मेमोरी मॉडल का पालन करेगा।

एक संकलक/जेवीएम जो सिंक्रनाइज़ेशन को हटा देता है, केवल उस माहौल में परिणाम देगा जहां मेमोरी मॉडल का उल्लंघन होता है। उदाहरण के लिए, इंटीजर वैल्यू के पढ़ने से पहले मेमोरी बाधा रखने वाले कंपाइलर/जेवीएम के बिना विधि-इन-लाइनिंग विधि को निष्पादित किया जा सकता है, जिससे कैश किए गए मान से स्टाल मानों को पढ़ने की अनुमति मिलती है।

* नोट, कंपाइलर/जेवीएम जोड़ी का संदर्भ जानबूझकर है। एक कंपाइलर केवल बाइटकोड उत्सर्जित करेगा जो जेएलएस का अनुपालन करता है; एक जेवीएम में बस एक बग हो सकता है जहां स्मृति मॉडल की आवश्यकताओं का अभी भी उल्लंघन किया जा सकता है। मेमोरी मॉडल की पूर्णता के लिए, कंपाइलर और जेवीएम दोनों को मेमोरी मॉडल द्वारा निर्धारित आवश्यकताओं का पालन करना चाहिए।

+0

हालांकि यह उत्तर मूल रूप से रैचेट फ्रीक के समान है, मुझे लगता है कि यह व्यवहार को स्पष्ट बनाता है - क्या मैं +2 दे सकता हूं? – Voo

+0

हॉटस्पॉट 1.6 के बाद से यह संभव है। लेकिन यह जावा कंपाइलर द्वारा नहीं हटाया गया है, लेकिन जेआईटी कंपाइलर द्वारा। यह दस्तावेज किया गया है कि 'स्ट्रिंगबफर' या 'हैशटेबल' बनाम 'स्ट्रिंगबिल्डर' या 'हैशमैप' में अनावश्यक सिंक्रनाइज़ेशन के कारण प्रदर्शन जुर्माना, यदि वे सिंगल थ्रेड में उपयोग किए जाते हैं तो हॉटस्पॉट जेवीएम 1.6 के बाद न्यूनतम होता है। देखें http://www.ibm.com/developerworks/java/library/j-jtp10185/ – Oliv

4

यह "सिंक्रनाइज़" को हटाने के लिए बिल्कुल सुरक्षित नहीं है यदि इरादा इसे थ्रेड-सुरक्षित बनाना है, जब तक कि आप सुनिश्चित न करें कि int वैरिएबल किसी अन्य तरीके से मुख्य मेमोरी में ठीक से सिंक्रनाइज़ किया गया है, इसलिए इस मामले में, नहीं।

+0

लेकिन (जब तक कि मैं गलत नहीं हूं) केवल लंबी और दोगुनी में संशोधन अस्थिर की आवश्यकता है, नहीं? – JVerstry

+5

नहीं, जब तक कि आप कभी भी इस प्रोग्राम को एकल-कोर प्रोसेसर पर नहीं चलाएंगे। यह परमाणु लिखने और पढ़ने के बारे में नहीं है। यह सीपीयू कैश और मुख्य मेमोरी के बीच आगे और पीछे स्थानांतरित होने के मूल्यों के बारे में है। एकाधिक थ्रेड ऑपरेटिंग के साथ एक बहु-कोर मशीन पर और "सिंक्रनाइज़" नहीं, अलग-अलग धागे एक ही चर के लिए अलग-अलग मान देख सकते हैं और प्रत्येक कोर के अन्य कैश में और मुख्य स्मृति से अलग कैश होगा। –

7

सिंक्रनाइज़ एक ताला हो रही के अलावा अन्य धागा सुरक्षा असर पड़ता है (संशोधित डेटा सुनिश्चित किसी एक अन्य सूत्र के लिए दिखाई देता है)

रूप में लंबे समय के रूप में इन दुष्प्रभावों वैध JIT क्या यह

चाहता है ऐसा करने के लिए अनिवार्य रूप से नि: शुल्क है कर रहे हैं

हालांकि उदाहरण में यह सुनिश्चित करने के लिए ताला चर की लोडिंग जो प्रभावी रूप से ताला

+1

पहला वाक्य यहां महत्वपूर्ण हिस्सा है। सिंक्रनाइज़ किया गया है किसी ऑब्जेक्ट की ** किसी ** विधि के बाद के किसी भी आमंत्रण के संबंध में पहले होता है। तो सिंक्रनाइज़ किए गए व्यवहार को यहां व्यवहार को हटा दें। – Voo

+0

जा रहे बिंदु। यह समझ में आता है। – JVerstry

5

ऐसे मामले हैं जब वीएम लॉक को खत्म कर सकता है। उदाहरण

भागने विश्लेषण के लिए

int bar() 
    Foo foo = new Foo(); 
    return foo.getWhatever(); 

वीएम कि foo कारण कर सकते हैं किसी भी अन्य धागे को दिखाई नहीं देता, इसलिए किसी और उसे लॉक करने की कोशिश करेंगे, getWhatever विधि के therfore ताला छोड़ा जा सकता है।

लॉक coarsening

Foo foo = ...; 
void bar() 
    a(); 
    foo.getWhatever(); 
    b(); 
    foo.getWhatever(); 
    c(); 

कानूनी तौर पर किया जा सकता है एक ताला कार्रवाई

void bar() 
    synchronized(foo) 
     a(); 
     foo.getWhatever_without_lock(); 
     b(); 
     foo.getWhatever_without_lock(); 
     c(); 

एक और अच्छी खबर यह बंद कर दिया क्षेत्र इतना कम है, अनुकूली लॉकिंग के कारण के बाद से है, वीएम सबसे अधिक संभावना इच्छा को बचाने के लिए विलय कर दिया इसके लिए स्पिन लॉक का उपयोग करें; असफल लॉकिंग के कारण थ्रेड निलंबन बहुत ही असंभव है।

+0

क्या आप इसके लिए संदर्भ दे सकते हैं? –

+0

@Ryan बस शब्दों को – irreputable

+0

देखें http://stackoverflow.com/questions/18996783/what-is-the-synchronization-cost-of-calling-a-synchronized-method-from-a-synchro – Raedwald

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

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