ThreadStatic 속성은 어떻게 작동합니까?


138

[ThreadStatic]속성 은 어떻게 작동합니까? 컴파일러는 TLS의 값을 채우거나 검색하기 위해 일부 IL을 방출한다고 가정했지만 분해를 보면 해당 수준에서 수행하지 않는 것 같습니다.

후속 조치로서, 정적이 아닌 멤버에 배치하면 어떻게됩니까? 우리는 개발자가 실수를 저지르고 컴파일러는 경고를하지도 않습니다.

최신 정보

두 번째 질문에 대한 답변 : 정적 C #으로 수정 된 ThreadStatic


1
생성 된 IL이 동일하면 (실제로) 런타임이 장식 된 필드에 도달 할 때 값을 할당하고 읽는 방법을 알 수 있도록 런타임을 구체적으로 코딩해야합니다. hack처럼 보인다 :)
Rex M

답변:


92

.NET jit 컴파일러에서 스레드 정적의 구현 의미는 IL 레벨 아래입니다. VB.NET 및 C #과 같이 IL로 방출하는 컴파일러는 ThreadStatic 특성을 가진 변수를 읽고 쓸 수있는 IL 코드를 방출하기 위해 Win32 TLS에 대해 아무것도 알 필요가 없습니다. C #이 아는 한 변수에는 특별한 것이 없습니다. 물건을 읽고 쓰는 위치 일뿐입니다. 그것이 속성이 있다는 사실은 C #에 아무런 영향을 미치지 않습니다. C #은 해당 심볼 이름에 대한 IL 읽기 또는 쓰기 명령어를 내기 만하면됩니다.

'무거운 리프팅'은 특정 하드웨어 아키텍처에서 IL이 작동하도록하는 핵심 CLR에 의해 수행됩니다.

그것은 왜 부적절한 (정적이 아닌) 심볼에 속성을 넣는 것이 컴파일러로부터 반응을 얻지 못하는지를 설명합니다. 컴파일러는 속성에 필요한 특수 의미를 모릅니다. 그러나 FX / Cop과 같은 코드 분석 도구는 이에 대해 알고 있어야합니다.

또 다른 방법 : CIL은 정적 (글로벌) 스토리지, 멤버 스토리지 및 스택 스토리지와 같은 스토리지 범위 세트를 정의합니다. TLS는 해당 목록에 없습니다. TLS가 해당 목록에있을 필요가 없기 때문일 가능성이 큽니다. 심볼에 TLS 속성이 태그되어있을 때 IL 읽기 및 쓰기 명령어가 TLS에 액세스하기에 충분하다면 왜 IL에 TLS에 대한 특별한 표현이나 처리가 있어야합니까? 필요하지 않습니다.


그러나 TLS의 특별한 구현 별 동작은 .NET / CLR의 "확인 가능한"판매 지점을 완전히 파괴하지 않습니까?
Dai

116

[ThreadStatic] 속성은 어떻게 작동합니까?

ThreadStatic 으로 표시된 필드 가 스레드에 연결되어 있고 수명이 스레드 수명과 비슷 하다고 생각할 수 있습니다 .

따라서 의사 코드에서 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]스레드 로컬 스토리지에 작성되므로 모든 스레드에는 필드 사본이 있습니다. 즉 필드 범위는 스레드에 로컬입니다.

TLS 필드는 gs / fs 세그먼트 레지스터를 통해 액세스합니다. 이러한 세그먼트는 OS 커널에서 스레드 특정 메모리에 액세스하는 데 사용됩니다. OS 커널에 의해 수행됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.