2011-01-08 3 views
4
// Member Variable 
private static readonly object _syncLock = new object(); 

// Now inside a static method 

foreach (var lazyObject in plugins) 
{ 
    if ((string)lazyObject.Metadata["key"] = "something") 
    { 
     lock (_syncLock) 
     { 
     // It seems the `IsValueCreated` is not up-to-date 
     if (!lazyObject.IsValueCreated) 
      lazyObject.value.DoSomething(); 
     } 
     return lazyObject.value; 
    } 
} 

ループごとに同期アクセスが必要です。このループを反復する多くのスレッドがあり、それらが探しているkeyに基づいて、遅延インスタンスが作成されて戻されます。MEFを使用したスレッドセーフな遅延インスタンス化

lazyObjectを1回以上作成しないでください。 Lazyクラスは、ロックを使用しているにもかかわらず、ハイスレッディングの下で​​複数のインスタンスが作成されています(これはvolatilestatic intInterlocked.Incrementで追跡し、どこかにログします)。問題は私がLazyの定義へのアクセス権を持っていないこととMEFLazyクラスがどのようにオブジェクトを作成するかを定義していることです。 CompositionContainerには、すでに使用されているコンストラクタ内のスレッドセーフなオプションがあることに気付くはずです。

私の質問:

1)なぜロックが機能しないのですか?

2)パフォーマンス向上のために、ロックの代わりにロックの配列を使用する必要がありますか?

+0

... if声明のタイプミスました。あなたは静的メンバー関数(コンパイルされません)によってアクセスされるクラスの非静的メンバー変数を持っています –

+0

もちろん静的です。編集されました。 – Xaqron

+0

'return lazyObject.value'をロック内に移動しようとします。 – jgauffin

答えて

4

LazyのデフォルトコンストラクタはTですか? MEFはLazyThreadSafetyMode.PublicationOnlyを使用します。つまり、ユニット化されたLazyにアクセスする各スレッドは、最初に完了するまでにnew()を生成します。その値は、現在.Valueにアクセスしているすべてのスレッドに対して返され、それ自身のnew()インスタンスは破棄されます。あなたのコンストラクタが複雑な場合(多すぎるかもしれません)、最小限の構築作業と別のメソッドへのコンフィグレーションの移動として再定義する必要があります。

あなたは全体の方法について考える必要があります。あなたは考慮する必要があります。

public IPlugin GetPlugin(string key) 
{ 
    mutex.WaitOne(); 

    try 
    { 
    var plugin = plugins 
     .Where(l => l.Metadata["key"] == key) 
     .Select(l => l.Value); 
     .FirstOrDefault(); 

    return plugin; 
    } 
    finally 
    { 
    mutex.ReleaseMutex(); 
    } 
} 

あなたはまた、あなたのコードが倒れさせ、それ以外の場合は、別のスレッド上で変更することができる、pluginsは読み取り専用されていない場合、あなたはあまりにもそのインスタンスへのアクセスを同期する必要があることを考慮する必要があります。

+0

ありがとうございます。ここで 'mutex'と同じことを'ロック 'しませんか? IsValueCreatedに同期アクセスすると、スレッドは別のインスタンスを作成しようとする可能性もありますか? – Xaqron

+0

'IsValueCreated'プロパティは、単に内部オブジェクトが初期化されているかどうかをチェックします。この内部プロパティ( 'LazyThreadSafetyModel.ExecutionAndPublication'がある場合に限る)は、初期化側に対して書き込み同期されることが保証されています。 'PublicationOnly'を通じて、これは保証されません。 –

+0

それは動作しませんでした。私は '増分'を 'DoSomthing()'メソッドに移しましたが、依然として増加しています。これはコンストラクタだけでなく、IsValueCreatedに関するものであることを意味します。 – Xaqron

0

このようなシナリオでは、具体的なコンストラクタLazy<T, TMetadata>があります。ここでは、Lazyインスタンスを構築するときにLazyThreadSafetyModeを定義します。そうでなければ、ロックはさまざまな理由で機能しない可能性があります。このLazy<T>インスタンスのValueプロパティにアクセスする唯一の場所でない場合は、

ところで、あなたは、私は何かが(それは難しいあなたが持っている問題を参照することができます)そのコードには非常に適切ではありません

+0

これは 'value'にアクセスする唯一の場所です。 'Lazy'コンストラクタについては、もう一度質問を読んでください。 – Xaqron

+0

あなたが投稿した記事から言うのは難しいですが、Matthewが上に書いているようにMEFが 'PublicationOnly'モードでLazyインスタンスを作成している場合、 'T'のインスタンスがいくつか作成される可能性があります'Value'プロパティに割り当てられたインスタンス他のインスタンスは、ドキュメントの状態が破棄されます。だから私の意見では(そして、 'プラグイン'は読み取り専用のコレクションであるという前提の下で)何もロックする必要はありません... –

関連する問題