Как работает атрибут ThreadStatic? - PullRequest
131 голосов
/ 08 марта 2011

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

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

Обновление

Второй ответ здесь: ThreadStatic Modified with StaticC #

Ответы [ 3 ]

109 голосов
/ 08 марта 2011

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

87 голосов
/ 08 марта 2011

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

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

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

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

5 голосов
/ 19 апреля 2018

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