2009-10-25 13 views
6

कुछ धागे पढ़ना (common concurrency problems, volatile keyword, memory model) मैं जावा में समवर्ती मुद्दों के बारे में उलझन में हूं।यदि एक से अधिक धागे किसी फ़ील्ड तक पहुंच सकते हैं तो इसे अस्थिर के रूप में चिह्नित किया जाना चाहिए?

मेरे पास बहुत से फ़ील्ड हैं जो एक से अधिक धागे से उपयोग किए जाते हैं। क्या मुझे उनके माध्यम से जाना चाहिए और उन्हें अस्थिर के रूप में चिह्नित करना चाहिए?

जब एक वर्ग मैं है कि क्या एक से अधिक थ्रेड इसे उपयोग करेंगे के बारे में पता नहीं कर रहा हूँ निर्माण, तो निश्चित रूप से यह किसी भी क्षेत्र जाने के लिए नहीं, अस्थिर हो तो मेरी समझ से वहाँ बहुत कम मामलों में आप इसका इस्तेमाल नहीं होता है असुरक्षित है । क्या ये सही है?

मेरे लिए यह संस्करण 1.5 जेवीएम और बाद में विशिष्ट है, लेकिन मेरे विशिष्ट सेटअप के बारे में जवाब देने तक सीमित नहीं है।

उत्तर

3

यदि फ़ील्ड को कई धागे से एक्सेस किया जाता है, तो यह volatile या final होना चाहिए, या केवल सिंक्रनाइज़ किए गए ब्लॉक के साथ उपयोग किया जाना चाहिए। अन्यथा, असाइन किए गए मान अन्य धागे के लिए दृश्यमान नहीं हो सकते हैं।

एक वर्ग को विशेष रूप से एकाधिक धागे द्वारा समवर्ती उपयोग के लिए डिज़ाइन किया जाना है। फ़ील्ड को अस्थिर या अंतिम चिह्नित करना थ्रेड-सुरक्षा के लिए पर्याप्त नहीं है। स्थिरता के मुद्दों (wait और notify का उपयोग कर उदाहरण के लिए), अंतर-धागा संकेत के बारे में चिंताओं (कई क्षेत्रों में परिवर्तन की atomicity), आदि

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

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

4

ठीक है, आप उन अन्य प्रश्न पढ़ा है और मुझे लगता है आप पहले से ही जवाब पढ़ा है, तो मैं बस कुछ महत्वपूर्ण बिंदुओं पर प्रकाश डाला जाएगा:

  1. वे बदलने के लिए जा रहे हैं? यदि नहीं, तो आपको अस्थिर
  2. की आवश्यकता नहीं है यदि हां, तो फिर किसी अन्य से संबंधित फ़ील्ड का मान है? यदि हां, तो बिंदु 4
  3. पर जाएं कि कितने धागे इसे बदल देंगे? अगर केवल 1, तो अस्थिर है, आपको
  4. की आवश्यकता है यदि नंबर 2 का उत्तर "नहीं" है या एक से अधिक धागे इसे लिखने जा रहे हैं, तो अकेले अस्थिर पर्याप्त नहीं है, आपको शायद इसकी आवश्यकता होगी पहुँच सिंक्रनाइज़

जोड़ा गया: क्षेत्र संदर्भ एक वस्तु है, तो यह अपने आप ही के क्षेत्र होगा और उन सभी को ध्यान भी इन क्षेत्रों के लिए लागू होता
हैं।

1

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

उस मामले पर विचार करें जहां परिवर्तनीय एक म्यूटेबल ऑब्जेक्ट (एक सरणी या संग्रह कहें) संदर्भित करता है, फिर उस ऑब्जेक्ट के साथ बातचीत करना थ्रेड सुरक्षित नहीं होगा क्योंकि संदर्भ अस्थिर है।

2

यदि आपको पूछना है, तो ताले का उपयोग करें। कुछ मामलों में volatile उपयोगी हो सकता है, लेकिन यह सही है, यह बहुत मुश्किल है। उदाहरण के लिए:

class Foo { 
    private volatile int counter = 0; 
    int Increment() { 
    counter++; 
    return counter; 
    } 
} 

दो धागे एक ही समय में Increment() चलाते हैं, तो यह संभव है परिणाम counter = 1 होने के लिए। ऐसा इसलिए है क्योंकि कंप्यूटर पहले counter पुनर्प्राप्त करेगा, एक जोड़ें, फिर उसे वापस सहेजें। अस्थिरता केवल अन्य बयानों के सापेक्ष एक विशिष्ट क्रम में सहेजने और लोड होने के लिए मजबूर करती है।

ध्यान दें कि synchronized आमतौर पर volatile के लिए की जरूरत है obviates - अगर सब एक भी क्षेत्र एक ही मॉनिटर द्वारा संरक्षित हैं करने के लिए पहुंचता है, तो volatile कभी भी आवश्यकता नहीं होगी।

लॉकलेस एल्गोरिदम बनाने के लिए volatile का उपयोग करना बहुत मुश्किल है; synchronized तक चिपके रहें जब तक कि आपके पास सख्त सबूत नहीं है कि यह पहले से ही धीमा है, और आपने जिस एल्गोरिदम को लागू करने की योजना बनाई है, उस पर विस्तृत विश्लेषण किया है।

+0

इस विशेष उपयोग के मामले के लिए, 'सिंक्रनाइज़' स्वयं का उपयोग करने के बजाय, AtomicInteger देखें। – erickson

+1

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

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

  • कोई संबंधित समस्या नहीं^_^