2012-08-06 24 views
8

क्या निम्न कोड एक ही समस्या का कारण बनेंगे, यदि इस विधि का चर 'सामान्यसेट' क्लास स्तर फ़ील्ड था। यदि यह कक्षा स्तर का क्षेत्र था, तो मुझे सिंक्रनाइज़ किए गए ब्लॉक के भीतर ऑपरेशन सेट करने के लिए जोड़ना होगा क्योंकि हैशसेट थ्रेड सुरक्षित नहीं है। मुझे निम्नलिखित कोड में ऐसा ही करना चाहिए, क्योंकि सेट पर एकाधिक थ्रेड जोड़ रहे हैं या यहां तक ​​कि वर्तमान थ्रेड सेट को म्यूटेट करने के लिए भी जा सकता है।थ्रेड सेफ - अंतिम स्थानीय विधि चर धागे पर पारित किया गया?

public void threadCreatorFunction(final String[] args) { 
    final Set<String> commonSet = new HashSet<String>(); 

    final Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      while (true) { 
       commonSet.add(newValue()); 
      } 
     } 
    }; 

    new Thread(runnable, "T_A").start(); 
    new Thread(runnable, "T_B").start(); 
} 

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

काफी कुछ इस से संबंधित प्रश्न होते हैं:

लेकिन, मैं उन्हें इस तरह के बंटवारे/mutables के निधन की धागा सुरक्षित भाग पर बल देते नहीं देख सकता।

+0

यह भी देखें http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-differen – nos

उत्तर

9

नहीं, यह बिल्कुल थ्रेड-सुरक्षित नहीं है। सिर्फ इसलिए कि आपको इसे अंतिम चर में मिला है, इसका मतलब है कि दोनों धागे एक ही संदर्भ देखेंगे, जो ठीक है - लेकिन यह ऑब्जेक्ट कोई और थ्रेड-सुरक्षित नहीं बनाता है।

या तो आपको एक्सेस सिंक्रनाइज़ करने की आवश्यकता है, या ConcurrentSkipListSet का उपयोग करें।

5

एक दिलचस्प उदाहरण है।

संदर्भ commonSet धागा सुरक्षित और अपरिवर्तनीय है। यह पहले धागे के लिए ढेर पर है और आपके अज्ञात Runnable वर्ग का एक क्षेत्र भी है। (आप इसे डीबगर में देख सकते हैं)

सेट commonSet संदर्भित है और थ्रेड सुरक्षित नहीं है। आपको इसे थ्रेड सुरक्षित बनाने के लिए सिंक्रनाइज़ या लॉक का उपयोग करने की आवश्यकता है। (या एक धागा सुरक्षित संग्रह के बजाय का उपयोग करें)

1

मुझे लगता है कि आप अपने पहले वाक्य में एक शब्द भी छूट रहे हैं:

विल निम्नलिखित कोड कारण एक ही समस्या है, तो चर 'commonSet' की इस पद्धति का एक ??? था इसके बजाय एक वर्ग स्तर क्षेत्र।

मुझे लगता है कि आप थोड़ा उलझन में हैं। समेकन संबंधी मुद्दों के साथ कुछ भी नहीं करना है कि आपके उत्परिवर्तनीय डेटा संरचना का संदर्भ final घोषित किया गया है या नहीं। आपको संदर्भ को final के रूप में घोषित करने की आवश्यकता है क्योंकि आप closing over हैं, यह Runnable के लिए अनाम आंतरिक कक्षा घोषणा के अंदर है। यदि आप वास्तव में डेटा संरचना को पढ़ने/लिखने के लिए कई धागे प्राप्त करने जा रहे हैं तो आपको या तो ताले (सिंक्रनाइज़) का उपयोग करने या java.util.concurrent.ConcurrentHashMap जैसी समवर्ती डेटा संरचना का उपयोग करने की आवश्यकता है।

+0

पहली पंक्ति को सही किया गया – haps10

+0

आह, मैं गलत था-आपके पास एक अतिरिक्त शब्द था! – DaoWen

0

जैसा कि अन्य ने पहले से ही टिप्पणी की है, आप अंतिम और सिंक्रनाइज़ की तरह कुछ अवधारणाओं को गलत समझ रहे हैं।

मुझे लगता है कि यदि आप समझते हैं कि आप अपने कोड के साथ क्या हासिल करना चाहते हैं, तो यह आपकी मदद करना बहुत आसान होगा। मुझे लगता है कि यह कोड स्निपेट एक उदाहरण है जो वास्तविक कोड है।

कुछ प्रश्न: फ़ंक्शन के अंदर सेट को परिभाषित क्यों किया गया है? इसे धागे के बीच साझा किया जाना चाहिए? कुछ है कि मुझे पहेली है कि आप टोकरा runnable

new Thread(runnable, "T_A").start(); 
    new Thread(runnable, "T_B").start(); 
0

का एक ही उदाहरण के साथ दो धागे commonset एकल थ्रेड या एक से अधिक द्वारा किया जाता है चाहे वह केवल संदर्भ है कि अंतिम वस्तुओं (के लिए अडिग है यानी, एक बार आप सौंपा एक और obj संदर्भ फिर से असाइन नहीं कर सकता) हालांकि आप उस संदर्भ का उपयोग कर इस ऑब्जेक्ट द्वारा संदर्भित सामग्री को अभी भी संशोधित कर सकते हैं।

यदि यह अंतिम एक धागा इसे फिर से प्रारंभ किया जा सकता था और संदर्भ जो मामले में commonSet = new HashSet<String>(); commonSet.add(newValue()); इन दो धागे दो अलग commonsets उपयोग कर सकते हैं जो शायद नहीं है कि आप क्या चाहते

1

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