.NET 4.0のSystem.Lazy<T>クラスは、私のように要約します列挙LazyThreadSafetyMode、を介して3スレッドセーフモードを提供しています:System.Lazy <T>は異なるスレッドセーフモードと
- LazyThreadSafetyMode.None - スレッドセーフではありません。
- LazyThreadSafetyMode.ExecutionAndPublication-1つの並行スレッドだけが、基礎となる値の作成を試みます。作成に成功すると、待機中のスレッドはすべて同じ値を受け取ります。未処理の例外が作成中に発生した場合は、待機中の各スレッドで再スローされ、キャッシュされ、後続の各値のアクセスに再スローされます。
- LazyThreadSafetyMode.PublicationOnlyから複数の同時実行スレッドは、基礎となる価値を創造しようとしますが、成功するために最初は、すべてのスレッドに渡された値を決定します。作成中に未処理の例外が発生した場合、そのオブジェクトはキャッシュされません。同時に&の基本値にアクセスしようとすると、作成が再試行されます。&が成功する可能性があります。
私はすなわち、わずかに異なるスレッドの安全規則を次のレイジー初期化された値を持っているしたいと思います:
つだけの同時スレッドが根底にある価値を創造しようとします。作成に成功すると、待機中のスレッドはすべて同じ値を受け取ります。未処理の例外が作成中に発生すると、待機中の各スレッドで再スローされますが、キャッシュされず、その後の値にアクセスしようとすると、作成が再試行されます。&が成功する可能性があります。
のでLazyThreadSafetyMode.ExecutionAndPublicationとキーdifferinceは、作成時に「最初に行くには、」失敗した場合、それは後で再試行することができるということです。
これらのセマンティクスを提供する既存の(.NET 4.0)クラスはありますか、それとも独自にロールバックする必要がありますか?私が自分自身をロールバックする場合、明示的なロック/同期を避けるために、既存のLazy <T>を実装内で再利用するスマートな方法がありますか?
N.B.ユースケースの場合、「作成」は高価で潜在的に断続的なエラーが発生する可能性があると想像してください。リモートサーバーから大量のデータを取得します。私はおそらくすべてが失敗するか、すべて成功するので、データを取得する複数の同時の試みをしたくないです。しかし、失敗した場合は、後で再試行することができます。
をひどく曖昧である "に後で再試行します"。おそらくLazyインスタンスを再作成するTimerを使用することができます。 –
こんにちは@HansPassant。私はLazy自体が後で再試行するべきではありません。つまり、ユーザーがmyLazy.valueを複数回呼び出すと、最初に失敗した場合、2回目の呼び出しで、以前の例外を単純に再実行するのではなく、基礎となる値をインスタンス化するように再試行します。 –
MattBecker82
「後で」はいつですか?メインスレッドがその例外をスローし、待機中のすべてのスレッドがそれを観察することによってブロック解除された後はいつですか?あなたの仮説的な 'LazyWithSprinkles'を監視している/呼び出している呼び出し元が管理していますか?あなたが投稿したものより少し大きい問題があるように思えます。これは 'Lazy 'に似ているものとはかなり異なる解決策を示唆しています。 –