2010-09-01 7 views
6

संभव डुप्लिकेट:
Thread safety in Java classजावा समेकन - एक सेटर सिंक्रनाइज़ क्यों नहीं करता है (लेकिन गेटटर नहीं) कक्षा थ्रेड-सुरक्षित बनाता है?

मैं अभ्यास में जावा संगामिति पढ़ रहा हूँ, और मैं एक उदाहरण है कि मुझे पहेली पर आए हैं।

लेखकों का कहना है कि इस वर्ग के threadsafe

public class MutableInteger { 

    private int number; 

    public int getInt() { 
     return number; 
    } 

    public void setInt(int val) { 
     number = val; 
    } 
} 

नहीं है और वे भी कहते हैं कि केवल एक ही विधि (उदाहरण के लिए सेटर) को सिंक्रनाइज़ नहीं कर सकता है; आपको दोनों को सिंक्रनाइज़ करना होगा।

मेरा प्रश्न है: क्यों? बसटर सिंक्रनाइज़ नहीं करना चाहते हैं?

+0

असल में यह अलग-अलग है। –

उत्तर

5

जावा मेमोरी मॉडल के बाद पहले होता है/होता है। लिखने के पथ और इस व्यवहार को ट्रिगर करने के लिए पढ़ने के पथ पर कुछ सामान्य समवर्ती निर्माण (उदा। सिंक्रनाइज़ ब्लॉक/विधि, ताला, अस्थिर, परमाणु) होना आवश्यक है।

यदि आप दोनों विधियों को सिंक्रनाइज़ करते हैं तो आप पूरे ऑब्जेक्ट पर लॉक बना रहे हैं जिसे पढ़ने और लिखने वाले थ्रेड दोनों द्वारा साझा किया जाएगा। JVM यह सुनिश्चित करेगा कि (सिंक्रनाइज़) सेटइन्ट विधि को छोड़ने से पहले होने वाले लेखन थ्रेड पर होने वाले कोई भी परिवर्तन किसी भी रीडिंग थ्रेड को (सिंक्रनाइज़) getInt विधि दर्ज करने के बाद दिखाई देंगे। JVM यह सुनिश्चित करने के लिए आवश्यक स्मृति बाधाओं को सम्मिलित करेगा कि यह होगा।

यदि केवल लेखन विधि सिंक्रनाइज़ होती है तो ऑब्जेक्ट में परिवर्तन किसी भी पठन थ्रेड पर दिखाई नहीं दे सकता है। ऐसा इसलिए है क्योंकि पढ़ने वाले पथ पर कोई बिंदु नहीं है कि JVM का उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि रीडिंग थ्रेड की दृश्यमान स्मृति (कैश इत्यादि) लेखन धागे के अनुरूप हैं। GetInt विधि सिंक्रनाइज़ किए गए इसे प्रदान करें।

नोट: विशेष रूप से इस मामले में क्षेत्र 'संख्या' अस्थिर बनाने से सही व्यवहार होगा क्योंकि अस्थिर पढ़ने/लिखने से भी जेवीएम में समान स्मृति दृश्यता व्यवहार प्रदान होता है और setInt विधि के अंदर की क्रिया केवल एक असाइनमेंट है।

+0

यह एक सामान्य टिप्पणी पंक्ति है। –

+0

फील्ड 'संख्या' अस्थिर बनाना बनाना असाइनमेंट ऑपरेशन परमाणु बनाता है। विधि को सिंक्रनाइज़ किया जाना चाहिए – John

+0

फ़ील्ड अस्थिर है और विधि सिंक्रनाइज़ नहीं होने पर वास्तविक विफलता परिदृश्य को समझाएं। –

-1

क्योंकि number अस्थिर नहीं है, और getInt(), सिंक्रनाइज़ getInt() पुराने मान वापस आ सकते हैं नहीं है। अधिक जानकारी के लिए, जावा मेमोरी मॉडल के बारे में पढ़ें।

+0

क्षमा करें, उत्तर कम से कम अपूर्ण है और संकेत मेरी आंखों के लिए बेकार है। उन्होंने एक ठोस समस्या पर एक स्पष्टीकरण मांगा (-1) –

5

यह नमूना से पहले किताब में विस्तार से बताया है (पेज 35):

"केवल सेटर सिंक्रनाइज़ किया जा रहा पर्याप्त नहीं होगा:। धागे प्राप्त बुला अभी भी पुराने मान को देखने के लिए सक्षम हो जाएगा"

स्थिर डेटा: जब पाठक धागा तैयार हो जाता है, तो यह एक पुराना मूल्य देख सकता है। जब तक सिंक्रनाइज़ेशन का उपयोग नहीं किया जाता है हर बार एक चर को तक पहुंचाया जाता है, तो उस चर के लिए एक स्टेल मान देखना संभव है। इससे भी बदतर, स्थिरता सभी या कुछ भी नहीं है: एक थ्रेड एक चर के एक अद्यतित मूल्य को देख सकता है लेकिन पहले लिखा गया था कि किसी अन्य चर के एक स्थिर मूल्य।

+0

** मैं ** पुस्तक पढ़ रहा हूं, कह रहा हूं कि "यह पुराने मूल्यों को देखने में सक्षम होगा" पर्याप्त नहीं है, मैं मौलिक चाहता हूं। –

+0

तो, आप इस बात पर विश्वास नहीं कर रहे हैं कि अगर गेटर सिंक्रनाइज़ नहीं किया गया है और आप इसके लिए साबित करना चाहते हैं, तो इसका क्या मतलब है? – Soundlink

+0

मैं समझना चाहता हूं क्यों। कारण यह है कि धागे चर के स्थानीय कैश किए गए मान रखते हैं, और पढ़ना कैश को फ्लश नहीं कर सकता है। यदि कैश वहां नहीं था, तो इससे कोई फर्क नहीं पड़ता कि सिंक्रनाइज़ किए गए तरीके थे या नहीं (दोनों ऑपरेशन परमाणु हैं) –

1

आप केवल सेटर विधि सिंक्रनाइज़ हैं, तो आप केवल गारंटी दे सकें विशेषता का गलत संशोधन नहीं किया जा सकता है, लेकिन आप इसे बासी मूल्य है यकीन है कि जब आप चर पढ़ने की कोशिश नहीं हो सकता।

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