ThreadStatic v.s. ThreadLocal <T>: более общий, чем атрибут?
[ThreadStatic]
определяется с использованием атрибута, а ThreadLocal<T>
использует общий.
Почему были выбраны различные дизайнерские решения?
Каковы преимущества и недостатки использования общих атрибутов в этом случае?
Ответы
Ответ 1
То, что сообщение в блоге, отмеченное в комментариях, не делает явным, но я считаю очень важным, что [ThreadStatic]
автоматически не инициализирует вещи для каждого потока. Например, скажите, что у вас есть это:
[ThreadStatic]
private static int Foo = 42;
Первый поток, который использует это, увидит, что Foo
инициализирован до 42
. Но последующих потоков не будет. Инициализатор работает только для первого потока. Поэтому вам нужно написать код, чтобы проверить, инициализирован ли он.
ThreadLocal<T>
решает эту проблему, предоставляя вам функцию инициализации (как показывает блог Рида), которые запускаются до того, как первый элемент доступа будет доступен.
На мой взгляд, нет преимущества использовать [ThreadStatic]
вместо ThreadLocal<T>
.
Ответ 2
ThreadStatic Инициализировать только в первом потоке, ThreadLocal Инициализировать для каждого потока. Ниже приведена простая демонстрация:
public static ThreadLocal<int> _threadlocal =
new ThreadLocal<int>(() =>
{
return Thread.CurrentThread.ManagedThreadId;
});
public static void Main()
{
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("First Thread: {0}", x);
}
}).Start();
new Thread(() =>
{
for (int x = 0; x < _threadlocal.Value; x++)
{
Console.WriteLine("Second Thread: {0}", x);
}
}).Start();
Console.ReadKey();
}
![enter image description here]()
Ответ 3
Основная идея ThreadStatic - поддерживать отдельную копию переменной для каждого потока.
class Program
{
[ThreadStatic]
static int value = 10;
static void Main(string[] args)
{
value = 25;
Task t1 = Task.Run(() =>
{
value++;
Console.WriteLine("T1: " + value);
});
Task t2 = Task.Run(() =>
{
value++;
Console.WriteLine("T2: " + value);
});
Task t3 = Task.Run(() =>
{
value++;
Console.WriteLine("T3: " + value);
});
Console.WriteLine("Main Thread : " + value);
Task.WaitAll(t1, t2, t3);
Console.ReadKey();
}
}
В приведенном выше фрагменте у нас есть отдельная копия value
для каждого потока, включая основной поток.
![введите описание изображения здесь]()
Итак, переменная ThreadStatic будет инициализирована значением по умолчанию для других потоков, кроме потока, на котором она создана.
Если мы хотим инициализировать переменную в каждом потоке по-своему, используйте ThreadLocal.
Ответ 4
Я использую оба в одном месте, потому что ThreadStatic Инициализируется только в первом потоке, ThreadLocal Initialize для каждого потока.
[ThreadStatic]
private static IOperationHolder<RequestTelemetry> operation;
private ThreadLocal<bool> status = new ThreadLocal<bool>(true);
//TODO: this method will move AOP start method
public void StartOperation(string functionName)
{
RequestTelemetry requestTelemetry = new RequestTelemetry { Name = functionName };
operation = telemetryClient.StartOperation(requestTelemetry);
}