Die Klasse unten ist eine Implementierung eines schnellen, thread-sicheren, "lock free", lazy initializer.
Ich sage "lock free", obwohl es nicht vollständig ist; Es verwendet eine Sperre, bis es initialisiert wird, und ersetzt dann den Aufruf, um die Daten mit einer, die nicht die Sperre verwenden. (Ähnlich wie eine doppelt geprüfte Sperre mit einem flüchtigen Mitglied; und aus Leistungstests erhalte ich v. ähnliche Ergebnisse.)
Meine Frage ist: Ist dies eine gute/sichere Sache, die man tun sollte?
(Nachdem ich dies geschrieben hatte, bemerkte ich, dass .net 4.0 eine LazyInit<T>
die dieselben Operationen und noch mehr ausführt, aber in einem sehr konstruierten Beispiel, das ich erstellt habe, war meine Implementierung etwas schneller :-) )
NB Die Klasse wurde geändert und umfasst nun Value
Mitglied, und flüchtig auf dem _get
class ThreadSafeInitializer<TOutput>
where TOutput : class
{
readonly object _sync = new object();
TOutput _output;
private volatile Func<TOutput> _get;
public TOutput Value { get { return _get(); } }
public ThreadSafeInitializer(Func<TOutput> create)
{
_get = () =>
{
lock (_sync)
{
if (_output == null)
{
_output = create();
_get = () => _output; // replace the Get method, so no longer need to lock
}
return _output;
}
};
}
}