थ्रेडस्टैटिक विशेषता कैसे काम करती है?


138

कैसे [ThreadStatic]विशेषता काम करती है? मैंने मान लिया कि संकलक टीएलएस में कुछ आईएल को सामान को पुनः प्राप्त / पुनः प्राप्त करने के लिए उत्सर्जित करेगा, लेकिन एक असंतुष्टता को देखते हुए ऐसा उस स्तर पर नहीं लगता है।

अनुवर्ती के रूप में, यदि आप इसे गैर-स्थैतिक सदस्य पर रखते हैं तो क्या होता है? हमारे पास एक डेवलपर था जो गलती करता है और संकलक एक चेतावनी भी नहीं देता है।

अपडेट करें

दूसरा सवाल यहाँ उत्तर दिया गया: थ्रेडस्टैटिक स्टैटिक सी # के साथ संशोधित


1
यदि IL जनरेट किया गया समान है (जो वास्तव में यह है), तो रनटाइम को विशेष रूप से यह जानने के लिए कोडित किया जाना चाहिए कि इस तरह के सजाए गए क्षेत्र को हिट करने पर मूल्य कैसे आवंटित और पढ़ा जाए। एक हैक की तरह लगता है :)
रेक्स एम

जवाबों:


92

थ्रेड स्टैटिक के कार्यान्वयन शब्दार्थ IL.it के संकलक में IL स्तर से नीचे हैं। कंपाइलर जो VB.NET और C # की तरह IL पर जाते हैं, उन्हें IL32 के बारे में कुछ भी जानने की जरूरत नहीं है ताकि IL कोड को पढ़ा जा सके और वह एक चर लिख सकता है जिसमें थ्रेडस्टैटिक विशेषता हो। चर के बारे में कुछ खास नहीं है जहाँ तक C # जानता है - यह केवल सामान पढ़ने और लिखने के लिए एक स्थान है। तथ्य यह है कि इस पर एक विशेषता है, सी # का कोई परिणाम नहीं है। C # को केवल IL को उस प्रतीक नाम के लिए निर्देश पढ़ने या लिखने के लिए जानना होगा।

The हेवी लिफ्टिंग ’कोर सीएलआर द्वारा किया जाता है जो एक विशेष हार्डवेयर आर्किटेक्चर पर आईएल काम करने के लिए जिम्मेदार है।

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

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


लेकिन क्या टीएलएस का वह विशेष, कार्यान्वयन-विशिष्ट व्यवहार .NET / CLR के "सत्यापन योग्य" विक्रय-बिंदु को पूरी तरह से विकृत नहीं करता है?
दाई

116

[थ्रेडस्टैटिक] विशेषता कैसे काम करती है?

आप सोच सकते हैं कि थ्रेडस्टैटिक के साथ चिह्नित क्षेत्र एक धागे से जुड़ा हुआ है और इसका जीवनकाल एक धागे के जीवनकाल के बराबर है।

तो छद्मकोड ThreadStaticमें समान (शब्दार्थ द्वारा) एक थ्रेड से जुड़ा एक कुंजी-मूल्य है:

Thread.Current["MyClass.myVariable"] = 1;
Thread.Current["MyClass.myvariable"] += 1;

लेकिन वाक्य रचना थोड़ा आसान है:

class MyClass {
  [ThreadStatic]
  static int myVariable;
}
// .. then
MyClass.myVariable = 1;
MyClass.myVariable += 1;

यदि आप इसे गैर-स्थैतिक सदस्य पर रखते हैं तो क्या होगा?

मेरा मानना ​​है कि इसे अनदेखा किया गया है:

    class A {
        [ThreadStatic]
        public int a;
    }
    [Test]
    public void Try() {
        var a1 = new A();
        var a2 = new A();
        a1.a = 5;
        a2.a = 10;
        a1.a.Should().Be.EqualTo(5);
        a2.a.Should().Be.EqualTo(10);
    }

इसके अतिरिक्त यह उल्लेखनीय है कि ThreadStaticसामान्य स्थैतिक क्षेत्रों की तुलना में किसी भी तुल्यकालन तंत्र की आवश्यकता नहीं है (क्योंकि राज्य साझा नहीं किया गया है)।


1
छद्म कोड की तरह दूसरा होना चाहिए "MyClass.myVariable", यह नहीं होना चाहिए?
अक्षयपर्व

मुझे सटीक प्रतिबंधों पर यकीन नहीं है, लेकिन मैं सिर्फ यह बताना चाहता था कि क्या यह स्पष्ट नहीं है कि यह एक आदिम प्रकार नहीं है। आप स्रोत को देखें, तो के लिए TransactionScopeवे गुंजाइश (के लिए वहाँ में सामान के सभी प्रकार की दुकान referencesource.microsoft.com/#System.Transactions/System/... )
Simon_Weaver

10

[थ्रेडस्टैटिक] प्रत्येक थ्रेड में एक ही चर के अलग-अलग संस्करण बनाता है।

उदाहरण:

[ThreadStatic] public static int i; // Declaration of the variable i with ThreadStatic Attribute.

public static void Main()
{
    new Thread(() =>
    {
        for (int x = 0; x < 10; x++)
        {
            i++;
            Console.WriteLine("Thread A: {0}", i); // Uses one instance of the i variable.
        }
    }).Start();

    new Thread(() =>
   {
       for (int x = 0; x < 10; x++)
       {
           i++;
           Console.WriteLine("Thread B: {0}", i); // Uses another instance of the i variable.
       }
   }).Start();
}

3

के साथ चिह्नित फ़ील्ड [ThreadStatic]थ्रेड लोकल स्टोरेज पर बनाई गई है, इसलिए हर थ्रेड के पास फ़ील्ड की अपनी प्रति है यानी फ़ील्ड का दायरा थ्रेड के लिए स्थानीय है।

TLS फ़ील्ड gs / fs सेगमेंट रजिस्टरों के माध्यम से एक्सेस कर रहे हैं। थिस सेगमेंट का उपयोग OS कर्नेल द्वारा थ्रेड-विशिष्ट मेमोरी तक पहुंचने के लिए किया जाता है। नेट कंपाइलर TLS में मान को सामान करने / पुनः प्राप्त करने के लिए किसी भी IL का उत्सर्जन नहीं करते हैं। यह ओएस कर्नेल द्वारा किया जाता है।

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