जावा में स्थानीय चर थ्रेड सुरक्षित क्यों हैं


91

मैं जावा में मल्टी-थ्रेडिंग पढ़ रहा था और मैं इस पर आता हूं

स्थानीय चर जावा में सुरक्षित हैं।

तब से मैं सोच रहा हूं कि स्थानीय चर कैसे / क्यों सुरक्षित हैं।

क्या कोई मुझे बता सकता है।


27
क्योंकि उन्हें स्टैक में आवंटित किया गया है। और धागे ढेर को साझा नहीं करते हैं .. प्रत्येक के लिए इसका अनूठा ..
रोहित जैन

जवाबों:


103

जब आप एक धागा बनाते हैं तो इसका अपना एक स्टैक बनाया जाएगा। दो थ्रेड्स में दो स्टैक होंगे और एक थ्रेड कभी भी अपने स्टैक को अन्य थ्रेड के साथ साझा नहीं करेगा।

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

स्टैनफोर्ड प्रोफेसर द्वारा यूट्यूब में बहुत अच्छा व्याख्यान है जो इस अवधारणा को समझने में आपकी मदद कर सकता है।


13
मुझे खेद है, आप गलत हैं, केवल आदिम स्थानीय चर स्टैक पर संग्रहीत हैं। बाकी सभी चर ढेर पर जमा हो जाते हैं। जावा 7 ने एस्केप एनालिसिस शुरू किया, जो कुछ वैरिएबल के लिए स्टैक में आवंटित कर सकता है
जतिन

6
ढेर केवल वस्तु के संदर्भ को ढेर पर रखता है। क्योंकि स्टैक साफ हो जाता है, इसलिए संदर्भ होता है। इसलिए यह कचरा संग्रह के लिए उपलब्ध है
जतिन

6
@ जतिन: आप सही हैं। जब मैं स्मृति का मतलब था, मेरा मतलब है कि वस्तुओं और प्राथमिकताओं के लिए मूल्यों के लिए संदर्भ-मूल्य (मुझे लगता है कि नौसिखिया डेवलपर्स भी जानते हैं कि ऑब्जेक्ट हथियार पर हैं)।
कोसा

2
@ नाम्बरी लेकिन अगर संदर्भ मूल्य एक साझा चर की ओर इशारा करता है। फिर हम कैसे कह सकते हैं कि यह धागा सुरक्षित है?
एच। रैबी

3
@hajder: साझा के रूप में एक चर क्या है? वहाँ से शुरू करो। या तो उदाहरण या वर्ग चर सही? नहीं स्थानीय चर और इस धागे में मार्को टॉपलिंक का जवाब पढ़ें, मुझे लगता है कि वह बिंदु है जिसके बारे में आप भ्रमित हैं।
कोसा

19

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

public void someMethod(){

   long threadSafeInt = 0;

   threadSafeInt++;
}

वस्तुओं के स्थानीय संदर्भ कुछ अलग हैं। संदर्भ स्वयं साझा नहीं किया गया है। हालाँकि संदर्भित ऑब्जेक्ट, प्रत्येक थ्रेड के स्थानीय स्टैक में संग्रहीत नहीं है। सभी वस्तुओं को साझा किए गए ढेर में संग्रहीत किया जाता है। यदि कोई ऑब्जेक्ट स्थानीय रूप से बनाया गया है, तो वह उस विधि से नहीं बचता है जिसे उसने बनाया था, यह थ्रेड सुरक्षित है। वास्तव में आप इसे अन्य तरीकों और वस्तुओं पर भी पारित कर सकते हैं जब तक कि इनमें से कोई भी विधि या वस्तु पारित वस्तु को अन्य थ्रेड्स के लिए उपलब्ध नहीं कराती है।


एग्रीकल्चर में एक गलती है, @ नंबरी रिस्पॉन्स के कमेंट्स को देखें
जतिन

यदि आप इस तथ्य की ओर इशारा कर रहे हैं कि localSafeInt alsways सिर्फ 0 होगा, तो 1 और फिर वैसे भी अच्छा है हटा दिया। तो यह दर्शाता है कि यह चर धागों के बीच साझा नहीं किया गया है और इस प्रकार बहु ​​सूत्रण से प्रभावित नहीं हुआ है .. मुझे लगता है कि आप इसे थोड़ा और अधिक इंगित कर सकते हैं कि
थ्रेडसेफ

14

कार्यक्षमता की परिभाषा जैसी विधियों के बारे में सोचें। जब दो धागे एक ही विधि को चलाते हैं, तो वे किसी भी तरह से संबंधित नहीं होते हैं। वे प्रत्येक प्रत्येक स्थानीय चर का अपना संस्करण बनाएंगे, और किसी भी तरह से एक दूसरे के साथ बातचीत करने में असमर्थ होंगे।

यदि चर स्थानीय नहीं हैं (उदाहरण के लिए वर्ग स्तर पर विधि के बाहर परिभाषित चर), तो वे उदाहरण से जुड़े होते हैं (विधि के एक भी रन के लिए नहीं)। इस स्थिति में, एक ही विधि को चलाने वाले दो धागे एक चर को देखते हैं, और यह थ्रेड-सुरक्षित नहीं है।

इन दो मामलों पर विचार करें:

public class NotThreadsafe {
    int x = 0;
    public int incrementX() {
        x++;
        return x;
    }
}

public class Threadsafe {
    public int getTwoTimesTwo() {
        int x = 1;
        x++;
        return x*x;
    }
}

पहले में, एक ही उदाहरण पर चलने वाले दो धागे एक NotThreadsafeही एक्स देखेंगे। यह खतरनाक हो सकता है, क्योंकि धागे एक्स को बदलने की कोशिश कर रहे हैं! दूसरे में, एक ही उदाहरण पर चलने वाले दो धागे Threadsafeपूरी तरह से अलग चर देखेंगे, और एक दूसरे को प्रभावित नहीं कर सकते।


6

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

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


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

1
एक स्थानीय चर विधि के दायरे के भीतर तात्कालिक रूप से एक वस्तु को पकड़ सकता है या नहीं रख सकता है, यह सवाल का हिस्सा नहीं था। यहां तक ​​कि अगर यह है, तो विधि साझा स्थिति तक पहुंच सकती है।
मार्को टोपोलनिक

6

नंबरी जैसे अन्य उत्तरों के अलावा।

मैं इंगित करना चाहता हूं कि आप anoymous प्रकार की विधि में एक स्थानीय चर का उपयोग कर सकते हैं:

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

इस अवैध कोड पर विचार करें:

public void nonCompilableMethod() {
    int i=0;
    for(int t=0; t<100; t++)
    {
      new Thread(new Runnable() {
                    public void run() {
                      i++; //compile error, i must be final:
                      //Cannot refer to a non-final variable i inside an
                      //inner class defined in a different method
                    }
       }).start();
     }
  }

यदि जावा ने इसे अनुमति दी (जैसे C # "क्लोजर" के माध्यम से करता है), तो एक स्थानीय चर अब सभी परिस्थितियों में थ्रेडसेफ़ नहीं होगा। इस स्थिति में, iसभी थ्रेड्स के अंत में मान होने की गारंटी नहीं है 100


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

5

धागे का अपना ढेर होगा। दो थ्रेड्स में दो स्टैक होंगे और एक थ्रेड कभी भी अपने स्टैक को अन्य थ्रेड के साथ साझा नहीं करेगा। स्थानीय चर प्रत्येक थ्रेड के अपने स्टैक में संग्रहीत होते हैं। इसका मतलब है कि थ्रेड्स के बीच स्थानीय चर कभी साझा नहीं किए जाते हैं।


3

मूल रूप से चार प्रकार के भंडारण हैं जो जावा में वर्ग सूचना और डेटा संग्रहीत करने के लिए हैं:

विधि क्षेत्र, ढेर, जावा स्टैक, पीसी

इसलिए मेथड एरिया और हीप को सभी थ्रेड्स द्वारा साझा किया जाता है, लेकिन प्रत्येक थ्रेड का अपना जावा स्टैक और पीसी होता है और जिसे किसी अन्य थ्रेड द्वारा साझा नहीं किया जाता है।

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

@Weston के पास अच्छा जवाब भी है।


1

थ्रेड स्टैक पर केवल स्थानीय चर संग्रहीत किए जाते हैं।

स्थानीय चर है कि primitive type(जैसे पूर्णांक, लंबे समय से ...) पर संग्रहीत किया जाता thread stackहै और इसके परिणामस्वरूप - अन्य धागा यह करने के लिए एक पहुँच नहीं है।

स्थानीय चर है कि reference type(उत्तराधिकारी के Object) 2 भागों से होता है - पता (जिस पर संग्रहीत किया जाता है thread stack) और वस्तु (जिस पर संग्रहीत किया जाता है heap)


class MyRunnable implements Runnable() {
    public void run() {
        method1();
    }

    void method1() {
        int intPrimitive = 1;

        method2();
    }

    void method2() {
        MyObject1 myObject1 = new MyObject1();
    }
}

class MyObject1 {
    MyObject2 myObject2 = new MyObject2();
}

class MyObject2 {
    MyObject3 myObject3 = MyObject3.shared;
}

class MyObject3 {
    static MyObject3 shared = new MyObject3();

    boolean b = false;
}

यहाँ छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.