3

(この関連する質問 をした後、まだ質問があります。 )

の全体的なアイデア(AFAIK)は、必要なときにのみLazy<T>オブジェクトを作成することです。なんで ?作るのにお金がかかるからです。

私が望む最後のことは、Expensiveオブジェクトが>1何度も作成されることです。

多くのスレッドが最終的に同じ参照を生成するかどうかは気にしません。私は彼らに複数のインスタンスを作成させたくないだけです。

したがって、Lazyinitializerこれを次のように処理しsyncLockます。

LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());

しかし、どうすれLazy<T>ばそれを処理できますか? msdn で検索しましたが、syncLockオーバーロードが見つかりませんでした ...

何が欠けていますか?

4

2 に答える 2

4

Lazy が内部でどのように機能するかを尋ねていますか? Lazy は、 MSDN のドキュメントに従って、1 つだけが作成されることを保証します。

デフォルトでは、Lazy オブジェクトはスレッドセーフです。つまり、コンストラクターがスレッド セーフの種類を指定しない場合、コンストラクターが作成する Lazy オブジェクトはスレッド セーフです。マルチスレッド シナリオでは、スレッド セーフな Lazy オブジェクトの Value プロパティにアクセスする最初のスレッドが、すべてのスレッドでの後続のすべてのアクセスのためにそれを初期化し、すべてのスレッドが同じデータを共有します。したがって、どのスレッドがオブジェクトを初期化するかは問題ではなく、競合状態は良性です。

実際に内部でどのように機能するかを尋ねている場合lock、何らかの種類を使用しているようです:

        object obj = Volatile.Read<object>(ref this.m_threadSafeObj);
        bool flag = false;
        try
        {
            if (obj != Lazy<T>.ALREADY_INVOKED_SENTINEL)
            {
                Monitor.Enter(obj, ref flag);
            }
            if (this.m_boxed == null)
            {
                boxed = this.CreateValue();
                this.m_boxed = boxed;
                Volatile.Write<object>(ref this.m_threadSafeObj, Lazy<T>.ALREADY_INVOKED_SENTINEL);
            }
            else
            {
                boxed = (this.m_boxed as Lazy<T>.Boxed);
                if (boxed == null)
                {
                    Lazy<T>.LazyInternalExceptionHolder lazyInternalExceptionHolder = this.m_boxed as Lazy<T>.LazyInternalExceptionHolder;
                    lazyInternalExceptionHolder.m_edi.Throw();
                }
            }
        }
        finally
        {
            if (flag)
            {
                Monitor.Exit(obj);
            }
        }

Monitor.Enter と Monitor.Exit の呼び出しに注意してください。

于 2012-12-02T05:35:10.073 に答える
3

を受け取るコンストラクターのオーバーロードを見たいようですねLazyThreadSafetyMode

Lazy<T> lazy = new Lazy<T>(() => new T, LazyThreadSafetyMode.ExecutionAndPublication);

Lazy<T>は基本的に のユーザーフレンドリーなバージョンでありLazyInitializer、シングルスレッドまたはマルチスレッドの init の正確な実装がその列挙型の背後に隠されています。

于 2012-12-02T05:33:30.787 に答える