Implications of Lazy<T> and threadsafe false
-
26-05-2021 - |
Domanda
What are the implications of the using the Lazy<T>
class and marking isThreadSafe: false
during initialization?
In a scenario where lazy needs to access instance members and not static members where the lazy is initialized inside the class constructor does this automatically require isThreadSafe: false
in all usages?
Soluzione
In a scenario where lazy needs to access instance members and not static members where the lazy is initialized inside the class constructor does this automatically require isThreadSafe: false in all usages?
No - The isThreadSafe
argument only affects how the value within the Lazy<T>
is created.
Basically, when you set it to false, the method to create the value will just create the value, set it to the internal storage, and return the value.
If you set it to true, then the creation will be wrapped inside of a lock
, preventing more than one thread from ever creating the object. This maps to LazyThreadSafetyMode.ExecutionAndPublication.
You can also specify PublicationOnly
explicitly, which will allow more than one value to be created, but then use an Interlocked.CompareExchange internally instead of a lock to make sure that the first completed creation routine's value is the one that's used for the object.
Note that none of these options has any affect at all on which members are used for computing the value - they only affect how the value itself is created. The access for everything other than creation is always thread safe. If you're initializing a Lazy<T>
instance member within a class constructor, you're effectively guaranteeing that there will be no synchronization required, so you could set isThreadSafe
to false - but that would also mean that there is absolutely no reason to use Lazy<T>
in this situation, since you're using explicit instantiation...
Altri suggerimenti
From MSDN:
Some
Lazy<T>
constructors have aBoolean
parameter namedisThreadSafe
that is used to specify whether theValue
property will be accessed from multiple threads. If you intend to access the property from just one thread, pass infalse
to obtain a modest performance benefit. If you intend to access the property from multiple threads, pass intrue
to instruct theLazy<T>
instance to correctly handle race conditions in which one thread throws an exception at initialization time.
You wrote...
In a scenario where lazy needs to access instance members and not static members where the lazy is initialized inside the class constructor does this automatically require isThreadSafe: false in all usages?
No, it has nothing to do with instance vs. static. It has to do with whether or not the value being lazy initialized will be accessed on multiple threads or not. If it will be accessed on multiple threads, use true
so that Lazy<T>
handles the race condition for you. If it will not be, use false
so that Lazy<T>
avoids taking a lock which will give you a very slight almost unnoticeable performance gain (taking uncontested locks is VERY fast).