แอตทริบิวต์ ThreadStatic ทำงานอย่างไร


138

วิธีการ[ThreadStatic]ทำงานของแอตทริบิวต์? ฉันคิดว่าคอมไพเลอร์จะปล่อย IL บางอย่างเพื่อรับ / เรียกคืนค่าใน TLS แต่เมื่อดูที่การถอดแยกดูเหมือนว่าจะไม่ทำในระดับนั้น

การติดตามผลจะเกิดอะไรขึ้นถ้าคุณใส่สมาชิกที่ไม่อยู่กับที่? เรามีนักพัฒนาที่ทำผิดพลาดและคอมไพเลอร์ไม่ได้แจ้งเตือน

ปรับปรุง

ตอบคำถามที่สองที่นี่: ThreadStatic แก้ไขด้วย Static C #


1
หาก IL ที่สร้างขึ้นนั้นเหมือนกัน (ซึ่งแน่นอนว่าเป็นจริง) จากนั้นรันไทม์จะต้องมีรหัสเฉพาะเพื่อทราบวิธีการจัดสรรและอ่านค่าเมื่อมันกระทบกับเขตข้อมูลที่ตกแต่ง ดูเหมือนจะเป็นแฮ็ค :)
Rex M

คำตอบ:


92

ความหมายของการใช้งานของสแตติกเธรดอยู่ต่ำกว่าระดับ IL ในคอมไพเลอร์. NET jit คอมไพเลอร์ที่ส่งไปยัง IL อย่าง VB.NET และ C # ไม่จำเป็นต้องรู้อะไรเกี่ยวกับ Win32 TLS เพื่อที่จะปล่อยรหัส IL ที่สามารถอ่านและเขียนตัวแปรที่มีแอตทริบิวต์ ThreadStatic ไม่มีอะไรพิเศษเกี่ยวกับตัวแปรเท่าที่ C # รู้ - มันเป็นแค่สถานที่สำหรับอ่านและเขียน ความจริงที่ว่ามันมีคุณสมบัติมันไม่มีผลกับ C # C # จำเป็นต้องรู้เท่านั้นที่จะปล่อย IL อ่านหรือเขียนคำแนะนำสำหรับชื่อสัญลักษณ์นั้น

'การยกของหนัก' ทำโดย CLR หลักที่รับผิดชอบในการทำให้ IL ทำงานบนสถาปัตยกรรมฮาร์ดแวร์เฉพาะ

นั่นจะอธิบายได้ว่าทำไมการวางแอตทริบิวต์ไว้บนสัญลักษณ์ (ไม่คงที่) ที่ไม่เหมาะสมจะไม่ได้รับปฏิกิริยาจากคอมไพเลอร์ คอมไพเลอร์ไม่ทราบว่าความหมายพิเศษที่แอททริบิวต้องการนั้นคืออะไร อย่างไรก็ตามเครื่องมือวิเคราะห์รหัสเช่น FX / Cop ควรรู้เกี่ยวกับมัน

อีกวิธีในการดู: CIL กำหนดชุดขอบเขตการจัดเก็บ: การจัดเก็บแบบคงที่ (ทั่วโลก) ที่เก็บข้อมูลสมาชิกและที่เก็บข้อมูลแบบกองซ้อน TLS ไม่ได้อยู่ในรายชื่อนั้นอาจเป็นเพราะ TLS ไม่จำเป็นต้องอยู่ในรายการนั้น หากคำแนะนำในการอ่านและเขียนของ IL นั้นเพียงพอสำหรับการเข้าถึง TLS เมื่อสัญลักษณ์ถูกแท็กด้วยแอ็ตทริบิวต์ TLS เหตุใด IL จึงควรมีการแสดงหรือการรักษาพิเศษสำหรับ TLS มันไม่จำเป็น


แต่นั่นไม่พิเศษพฤติกรรมการใช้งานเฉพาะของ TLS ล้มล้างจุดขาย "ตรวจสอบได้" ของ. NET / CLR อย่างสมบูรณ์หรือไม่
ได

116

แอตทริบิวต์ [ThreadStatic] ทำงานอย่างไร

คุณสามารถคิดได้ว่าฟิลด์ที่มีการทำเครื่องหมายด้วยThreadStaticนั้นเชื่อมต่อกับเธรดและอายุการใช้งานนั้นเทียบได้กับอายุการใช้งานของเธรด

ดังนั้นใน pseudocode 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"อย่างนั้นใช่ไหม?
akshay2000

ฉันไม่แน่ใจว่ามีข้อ จำกัด ที่แน่นอน แต่ฉันต้องการชี้ให้เห็นว่าไม่ชัดเจนว่าไม่จำเป็นต้องเป็นแบบดั้งเดิม ถ้าคุณดูที่แหล่งที่มาสำหรับTransactionScopeพวกเขาเก็บทุกประเภทของสิ่งที่อยู่ในที่นั่นขอบเขต ( referencesource.microsoft.com/#System.Transactions/System/... )
Simon_Weaver

10

[ThreadStatic] สร้างตัวแปรเดียวกันในแต่ละเธรด

ตัวอย่าง:

[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]จะถูกสร้างบน Thread Local Storage ดังนั้นทุกเธรดจะมีสำเนาของฟิลด์เองเช่นขอบเขตของฟิลด์นั้นเป็นโลคัลสำหรับเธรด

ฟิลด์ TLS เป็นการเข้าถึงผ่านการลงทะเบียนเซกเมนต์ gs / fs เซ็กเมนต์เหล่านี้ถูกใช้โดยเคอร์เนล OS เพื่อเข้าถึงหน่วยความจำเฉพาะเธรดคอมไพเลอร์. net จะไม่ปล่อย IL ใด ๆ เพื่อคัด / เรียกค่าใน TLS มันทำโดยเคอร์เนลระบบปฏิบัติการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.