1

コード内の安全でないスレッドで発生している可能性のある問題を分析しようとしています。

私のmvc3 webapplicationでは、次のことを試みます:

// Caching code
public static class CacheExtensions
{
    public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator)
    {
        var result = cache[key];
        if(result == null)
        {
          result = generator();
          lock(sync) {
              cache[key] = result;
          }
        }
    return (T)result;
    }
}

次のようにキャッシングを使用します。

// Using the cached stuff
public class SectionViewData 
{
    public IEnumerable<Product> Products {get;set;}
    public IEnumerable<SomethingElse> SomethingElse {get;set;}
}

private void Testing() 
{
    var cachedSection = HttpContext.Current.Cache.GetOrStore("Some Key", 0 => GetSectionViewData());

    // Threading problem?
    foreach(var product in cachedSection.Products)
    {
         DosomestuffwithProduct...
    }
}

private SectionViewData GetSectionViewData() 
{
    SectionViewData viewData = new SectionViewData();
    viewData.Products = CreateProductList();
    viewData.SomethingElse = CreateSomethingElse();

    return viewData;
}

IEnumerable で inte 問題を実行できますか? スレッドの問題についてはあまり経験がありません。他のスレッドがキャッシュに新しい値を追加しても、cachedSection は変更されませんか? 私にとってこれはうまくいくでしょう!

製品とSomethingElseを個別にキャッシュする必要がありますか? SectionViewData 全体をキャッシュするよりも良いでしょうか??

4

2 に答える 2

1

スレッド化は難しいです。

メソッドでは、GetOrStoreget/generator シーケンスが完全に同期されていないため、任意の数のスレッドがキャッシュから null を取得し、同時にジェネレータ関数を実行できます。これは問題になる場合とそうでない場合があります。

あなたのlockステートメントは、キャッシュ[文字列]のセッターのみをロックします。これは、すでにスレッドセーフであり、「余分にロックする」必要はありません。

キャッシュ内のダブルチェック ロックのバリエーションが疑わしいので、それを取り除こうと思います。lock() セクションに入らないスレッドresultはメモリ バリアなしで取得できるためresult、スレッドが取得するまでに完全に構​​築されていない可能性があります。

キャッシュされた IEnumrator の列挙は、それらが同時に変更されない限り安全です。GetSectionViewData()不変の (不変の) コレクションを持つオブジェクトを返す場合は、安全です。

于 2012-10-05T21:44:42.830 に答える
0

あなたのコードには、製品がどのように取り込まれるかのような部分がありませんか? GetSectionViewData だけですか? もしそうなら、あなたのコードに大きな問題は見られません。ただし、2 つのスレッドが同じキーに対して同じデータ (CachedSection) を生成する可能性があります。作業を 2 回行っていることを除けば、スレッドの問題は発生しないはずです。したがって、これがコストのかかる操作である場合は、コードを変更します。キーごとに 1 回だけ生成します。高価でなければ、このままで十分です。

Products の IEnumerable は変更されません (スレッドごとに個別に作成すると仮定しますが、キャッシュ上の列挙子は挿入操作ごとに変更されるため、スレッドセーフではありません。したがって、これを使用している場合は注意が必要です。

于 2012-10-05T21:41:21.663 に答える