2015-12-25 3 views
4

Мне интересно, если следующий пример код потокобезопасно:ThreadStatic ленивого

public class Test 
{ 
    [ThreadStatic] 
    private static Foo current; 

    public static Foo GetFoo() 
    { 
     return current ?? (current = new Foo()); 
    } 
} 

public class Foo 
{ 
} 

Обычно, я хотел бы использовать Lazy<T>, но так как есть отдельная переменная в одном потоке, свойство должно быть по своей природе резьбовым безопасно, это правильно?

Спасибо.

+0

[MSDN] (https://msdn.microsoft.com/en-us/library/system.threadstaticattribute (v = vs.110) .aspx) четко отвечает на ваш вопрос ' статическое поле, помеченное с помощью ThreadStaticAttribute, не разделяется между потоками. Каждый исполняемый поток имеет отдельный экземпляр поля и независимо устанавливает и получает значения для этого поля. Если поле доступно в другом потоке, оно будет содержать другое значение. ', Поэтому хорошая практика - выработайте себе хотя бы документацию, если застряли - обратитесь за помощью к сообществу – sll

+0

Короткий ответ: да, это полностью поточно-безопасный , Каждый поток, который вызывает 'GetFoo()', будет получать свой собственный «Foo» singleton, лениво. – Cameron

ответ

4

Код, который вы предоставляете, отлично выглядит поточно. Если вам удобно с Lazy<T>, вы можете использовать ThreadLocal<T>, который работает аналогичным образом, но сохраняет свое значение потокобезопасным и потоком.

// Thread-Local variable that yields a name for a thread 
ThreadLocal<string> ThreadName = new ThreadLocal<string>(() => 
{ 
    return "Thread" + Thread.CurrentThread.ManagedThreadId; 
}); 

https://msdn.microsoft.com/en-us/library/dd642243(v=vs.110).aspx

+0

Правильно, но если .NET is> = 4.x – sll

+0

Вы должны использовать ... ** потому что ** ...? –

+0

Хорошая точка. Мой «ответ» скорее напоминает предложение, чем ответ на вопрос. – Wouter

1

код действительно Thread -Safe, но имейте это в виду, что каждый Thread будет иметь свой собственный экземпляр, что означает, в Singleton, например, что вы не должны хотеть использовать ThreadStaticAttribute.

Более полезное использование, которое я нашел для этого атрибута, составляет не Thread -секретные классы Thread -safe - например, Random.

Random.Next может вернуться 0, если вызывается из нескольких Threads, что делает его ThreadStatic делает экземпляры различны для каждого Thread.

С другой стороны, ThreadStatic не инициализирует поле автоматически для каждого Thread.

ThreadLocal<T> С другой стороны, вы можете предоставить метод инициализации, который используется как Lazy<T>, и инициализирует материал для вас при первом доступе на каждом Thread.

Обратите внимание, что ThreadLocal<T> потребует от вас получить доступ к фактическим данным через его собственность Value.

Кроме того, ваша инициализация в методе GetFoo в любом случае, так что каждый экземпляр будет инициализирован с ThreadStatic тоже.

Смежные вопросы