Как работает атрибут ThreadStatic?


Как [ThreadStatic] атрибут работы? Я предположил, что компилятор будет выдавать некоторый IL для заполнения/извлечения значения в TLS, но, глядя на разборку, он, похоже, не делает этого на этом уровне.

как следствие, что произойдет, если вы поместите его на нестатический элемент? У нас был разработчик, который сделал эту ошибку, и компилятор даже не предложил предупреждение.

обновление

второй вопрос ответил Здесь: ThreadStatic изменен со статическим C#

3 120

3 ответа:

семантика реализации статического потока находится ниже уровня IL в компиляторе .NET jit. Компиляторы, которые излучают в IL like VB.NET и C# не нужно ничего знать о Win32 TLS, чтобы выдавать код IL, который может читать и записывать переменную, которая имеет атрибут ThreadStatic. Насколько известно C#, в переменной нет ничего особенного-это просто место для чтения и записи материала. Тот факт, что он имеет атрибут имеет никакого значения в C#. C# нужно только знать, чтобы выделите IL инструкции чтения или записи для этого имени символа.

"тяжелая работа" выполняется основной средой CLR, которая отвечает за работу IL на определенной аппаратной архитектуре.

Это также объясняет, почему размещение атрибута на неподходящем (нестатическом) символе не получает реакции от компилятора. Компилятор не знает, какая специальная семантика требуется для атрибута. Однако инструменты анализа кода, такие как FX/Cop, должны знать о оно.

другой способ взглянуть на это: CIL определяет набор областей хранения: статическое (глобальное) хранилище, хранилище элементов и хранилище стека. TLS нет в этом списке, очень вероятно, потому что TLS не должен быть в этом списке. Если инструкции чтения и записи IL достаточны для доступа к TLS, когда символ помечен атрибутом TLS, почему IL должен иметь какое-либо специальное представление или обработку для TLS? В этом нет необходимости.

как [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 не требует никакого механизма синхронизации по сравнению с обычными статическими полями (потому что состояние не является общим).

[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();
}