2010-03-26 32 views
9

मुझे जावा के सत्यापन के बारे में कुछ प्रश्न हैं।जावा असाइनमेंट मुद्दे - क्या यह परमाणु है?

  • स्ट्रिंग्स

मैं एक वर्ग मिल गया है:

public class Test { 
private String s; 

public synchronized void setS(String str){ 
    s = s + " - " + str; 
} 

public String getS(){ 
    return s; 
} 
} 

मैं कर रहा हूँ "सिंक्रनाइज़" का उपयोग कर मेरी सेटर में है, और क्योंकि मेरे एप्लिकेशन में मेरी गेटर में यह से बचने,, डेटा गेटिंग्स और बहुत कम सेटिंग्स हैं। असंगतता से बचने के लिए सेटिंग्स को सिंक्रनाइज़ किया जाना चाहिए। मेरा सवाल है: एक परिवर्तनीय परमाणु प्राप्त और स्थापित कर रहा है? मेरा मतलब है, एक बहुप्रचारित वातावरण में, थ्रेड 1 परिवर्तनीय एस सेट करने वाला है, जबकि थ्रेड 2 "एस" प्राप्त करने वाला है। क्या कोई तरीका है कि गेटर विधि पुराने के मूल्य या एस के नए मूल्य से कुछ अलग हो सकती है (मान लीजिए कि हमारे पास केवल दो धागे हैं)? मेरे ऐप में नया मान प्राप्त करने में कोई समस्या नहीं है, और पुराने को पाने में कोई समस्या नहीं है। लेकिन क्या मुझे कुछ और मिल सकता है?

  • हैश मैप के प्राप्त करने और डालने के बारे में क्या?

इस पर विचार:

public class Test { 
     private Map<Integer, String> map = Collections.synchronizedMap(new HashMap<Integer, String>()); 

     public synchronized void setMapElement(Integer key, String value){ 
     map.put(key, value); 
     } 

     public String getValue(Integer key){ 
     return map.get(key); 
     } 
} 

डालने और परमाणु हो रही है? हैश मैप कैसे इसमें तत्व डालता है? क्या यह पहले पुराने मूल्य को हटा देता है और अब एक डाल देता है? क्या मैं पुराने मूल्य या नए मूल्य के अलावा अन्य प्राप्त कर सकता हूं?

अग्रिम धन्यवाद!

+0

+1 यह निर्दिष्ट करने के लिए कि पाठकों को पूर्ण नवीनतम मूल्य देखने की आवश्यकता नहीं है। बेशक, यह निश्चित रूप से उत्पादन कोड में दस्तावेज किया जाना चाहिए। –

उत्तर

6

पहले मामले में, String असुरक्षित प्रकाशन ("नए" जावा मेमोरी मॉडल (जेएमएम) में सुरक्षित होने के लिए सुरक्षित होता है, तो यह ठीक है।

volatile नहीं होने के कारण सैद्धांतिक रूप से कुछ समस्या है, जिसमें अद्यतित मूल्य नहीं है, लेकिन फिर अद्यतित होने का अर्थ स्पष्ट नहीं है। आप लॉक को एक तुलना-रेत-स्वैप (सीएएस) लूप के साथ प्रतिस्थापित कर सकते हैं, लेकिन संभवतया आपको अधिक प्रदर्शन लाभ नहीं मिलेगा कि लॉक की दलील होने की संभावना है या नहीं।

HashMap के मामले में, एक अनसंक्रनाइज़ नक्शा पढ़ने के लिए सुरक्षित नहीं है अगर इसे एक और धागा लिखना है, यहां तक ​​कि एक लेखक धागा भी। वास्तव में, यह लोकप्रिय सॉफ्टवेयर चलाने वाले उत्पादन प्रणालियों पर अनंत लूप का कारण बन गया है। प्रश्न में कोड वास्तव में मानचित्र के लिए दो ताले का उपयोग करता है, जो शीर्ष पर है (यद्यपि यदि आप इटरेटर का उपयोग करते हैं तो आपको उसी लॉक के स्पष्ट पकड़ की आवश्यकता होगी)। final नहीं है असुरक्षित प्रकाशन के लिए युक्त कक्षा को सुरक्षित होने से रोकता है। यदि mapvolatile था और आपने प्रत्येक put के लिए एक नया मानचित्र बनाया है, तो इसे प्राप्त करने के बिना सिंक्रनाइज़ेशन के बिना सुरक्षित किया जा सकता है।

+0

मैं संग्रह .synchronizedMap का उपयोग कर रहा हूँ। क्या यह भी खतरनाक है? मैं केवल अपने सेटर्स में संरचनात्मक संशोधन कर रहा हूं। तो मैं इन तरीकों को सिंक्रनाइज़ करता हूं, लेकिन मेरे गेटर्स को डेटा मिल जाता है। क्या मुझे उन्हें सिंक्रनाइज़ करना चाहिए? मुझे डर है कि जब मैं हैश मैप में एक मूल्य निर्धारित कर रहा हूं, तो दूसरा धागा मान प्राप्त करना चाहता है, और यह पुराने मूल्य या नए से कुछ और मिलता है। – Bob

+0

'संग्रह। सिंक्रनाइज़मैप 'सिंक्रनाइज़ेशन जोड़ता है, क्योंकि इसका नाम सुझाता है, इसलिए आपको यह नहीं करना है। यदि आप अपना कोड इनलाइन करते हैं और सीधे 'हैश मैप' का उपयोग करते हैं तो आपको बेहतर विचार मिल सकता है। –

6

इसे अपने हैश मैप को सिंक्रनाइज़ करने के लिए कुछ लपेटने के बजाय, java.util.concurrency.ConcurrentHashMap का उपयोग करने पर विचार करें।

यह हैश मैप का एक अद्यतन संस्करण है जो गारंटी देता है "पुनर्प्राप्तियां अपने शुरुआती दिनों में हाल ही में किए गए नवीनतम अपडेट ऑपरेशन के परिणामों को प्रतिबिंबित करती हैं।"

3

पहले उत्तर यह इंगित करने में सही हैं कि नए (1.5+) JVMs के साथ, डेटा भ्रष्टाचार के संबंध में स्ट्रिंग संस्करण सुरक्षित है। और आपको नकारात्मक सिंक्रनाइज़ पहुंच के बारे में पता होना प्रतीत होता है; परिवर्तनों की वजह से गेटर्स के माध्यम से जरूरी नहीं है।

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

+0

मेरा ऐप ऐप की तरह एक "ब्लॉग इंजन" है। मैं एक चर में नव निर्मित प्रविष्टियों के पहले एक्स (चलो कहते हैं 10) स्टोर करते हैं। यह कोई समस्या नहीं है कि उपयोगकर्ताओं को प्रवेश के अद्यतित संस्करण नहीं मिलते हैं, क्योंकि वे पृष्ठ को रीफ्रेश कर सकते हैं यदि वे चाहते थे। मैं एक दिन (सेटर) में लगभग 20 प्रविष्टियां करता हूं, लेकिन मुझे दिन में सैकड़ों आगंतुक मिलते हैं। गेटटर विधियों को सिंक्रनाइज़ करने के लिए यह कुशल नहीं है (मुझे लगता है) (मुझे ऊपर की तरह बहुत सारे गेटर विधियां मिल गई हैं)। (नहीं, मुझे अभी तक सैकड़ों हजारों आगंतुक नहीं मिला है, लेकिन मैं चाहता हूं कि मेरा ऐप इसे संभालने में सक्षम हो) – Bob

+5

ध्यान दें कि यह पृष्ठ को रीफ्रेश करने वाले उपयोगकर्ता की बात नहीं है। जावा मेमोरी मॉडल में, अगर सेटटर थ्रेड और गेटर थ्रेड के बीच कोई सिंक्रनाइज़ेशन नहीं है, तो यह संभव है कि गेटर थ्रेड * अपडेटेड मान कभी नहीं मिलेगा। यह मेरे लिए समयपूर्व अनुकूलन प्रकार की तरह लगता है। इसे पहले सही करें। यदि आप बाद में देखते हैं कि सिंक्रनाइज़ेशन वास्तव में आपके थ्रूपुट को सीमित कर रहा है, तो आप इसे संभालने के बेहतर तरीके देख सकते हैं। –

+0

"यह संभव है कि गेटर थ्रेड को अद्यतन मूल्य कभी नहीं मिलेगा।" कैसे? मुझे यह बिलकुल समझ में नहीं आया। "35 सेकंड 300 मिलीसेक" मुझे मूल्य मिलता है, यह पुराना है। "35 सेकंड 500 मिलीसेक" मैंने मूल्य निर्धारित किया है, "50 सेकंड xxx मिलीसेक" से मैं नया प्राप्त करने का प्रयास करता हूं? यह कैसे संभव है कि मुझे कभी भी नया मूल्य नहीं मिलेगा? – Bob

1

बहु थ्रेडेड वातावरण में आपको ग्राहक को s का सबसे अद्यतित मूल्य देखने के लिए गेटटर सिंक्रनाइज़ करने की आवश्यकता होगी।

+0

परिवर्तनीय "अस्थिर" बनाना उतना ही प्रभावी होगा और सिंक्रनाइज़ेशन ओवरहेड की आवश्यकता नहीं है –

+2

'अस्थिर' का अपना सिंक्रनाइज़ेशन ओवरहेड अंतर्निहित है। – Bombe

2

शायद Read Write Lock आपकी समस्या का समाधान कर सकता है?

इसके प्रलेखन पर एक नज़र डालें:

एक पढ़ने-लिखने की लॉक एक पारस्परिक अपवर्जन ताला द्वारा अनुमति दी है कि तुलना में साझा डेटा तक पहुँचने में संगामिति का एक बड़ा स्तर के लिए अनुमति देता है। यह इस तथ्य का फायदा उठाता है कि एक समय में केवल एक ही धागा (एक लेखक धागा) साझा डेटा को संशोधित कर सकता है, कई मामलों में किसी भी संख्या में थ्रेड एक साथ डेटा (इसलिए पाठक धागे) को पढ़ सकते हैं। सिद्धांत रूप में, रीड-राइट लॉक के उपयोग से अनुमत समेकन में वृद्धि से पारस्परिक बहिष्करण लॉक के उपयोग पर प्रदर्शन सुधार होगा। ....

+0

+1 लेकिन मुझे आश्चर्य होगा अगर सिंक्रनाइज़ किए गए संग्रह पहले से ही इसका उपयोग नहीं करते हैं। – HRJ

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