9

次の仮定はこのコードに有効ですか?コードの下にいくつかの背景情報を入れましたが、それは適切ではないと思います。

仮定1:これは単一のアプリケーションであるため、単一のプロセスで処理されると仮定しています。したがって、静的変数はスレッド間で共有され、ロックオブジェクトのコレクションを静的に宣言することは有効です。

仮定2:値がすでにディクショナリにあることがわかっている場合は、読み取りをロックする必要はありません。ConcurrentDictionaryを使用することもできますが、列挙(または削除)していないため、これは安全であり、値は存在し、を呼び出しても変更されないと思いますUnlockOnValue()

仮定3:基になるデータ構造が変更されても、その参照は変更されないため、Keysコレクションをロックできます。

private static Dictionary<String,Object> LockList = 
    new Dictionary<string,object>();

private void LockOnValue(String queryStringValue)
{
    lock(LockList.Keys)
    {
        if(!LockList.Keys.Contains(queryStringValue))
        {
            LockList.Add(screenName,new Object());
        }
        System.Threading.Monitor.Enter(LockList[queryStringValue]);
    }
}

private void UnlockOnValue(String queryStringValue)
{
    System.Threading.Monitor.Exit(LockList[queryStringValue]);
}

次に、このコードを次のように使用します。

LockOnValue(Request.QueryString["foo"])
//Check cache expiry
//if expired
    //Load new values and cache them.
//else
    //Load cached values
UnlockOnValue(Request.QueryString["foo"])

背景: クエリ文字列内の単一のユーザー定義変数に基づいてデータをダウンロードするアプリをASP.NETで作成しています。値の数はかなり制限されます。指定した期間、各値の結果をキャッシュする必要があります。

アプローチ:ローカルファイルを使用してデータをキャッシュすることにしました。これは最善のオプションではありませんが、これは重要ではなく、パフォーマンスは大きな問題ではないため、試してみたかったのです。オプションごとに2つのファイルを使用しました。1つはキャッシュの有効期限があり、もう1つはデータがあります。

問題:ロックを行うための最良の方法がわからず、.NETのスレッドの問題にあまり精通していません(このアプローチを選択した理由の1つ)。入手可能なものと私が読んだものに基づいて、私は上記がうまくいくはずだと思いましたが、私は確信が持てず、セカンドオピニオンを望んでいました。

4

2 に答える 2

7

現在のソリューションはかなり良さそうです。私が変更する2つのこと:

1: UnlockOnValue は、finally ブロックに入れる必要があります。例外がスローされた場合、そのロックは解放されません。

2: LockOnValue は辞書検索を 2 回行うため、やや非効率的です。これは小さなディクショナリでは大したことではありませんが、大きなディクショナリでは TryGetValue に切り替える必要があります。

また、少なくとも今のところ、仮定 3 が成り立ちます。ただし、ディクショナリ コントラクトは、Keys プロパティが常に同じオブジェクトを返すことを保証しません。そして、これに頼らないのはとても簡単なので、私はそれをお勧めしません. ロックオンするオブジェクトが必要なときはいつでも、そのためだけにオブジェクトを作成します。何かのようなもの:

private static Object _lock = new Object();
于 2012-07-24T17:04:32.700 に答える
1

lock単一のプロセスのスコープのみを持ちます。複数のプロセスにまたがりたい場合は、Mutex(named) のようなプリミティブを使用する必要があります。

lockMonitor.Enterは とと同じMonitor.Exitです。Monitor.Enterとも行う場合はMonitor.Exit、冗長です。

読み取りをロックする必要はありませんが、値が存在しないかどうかを確認して追加する「トランザクション」をロックする必要があります。その一連の命令をロックしないと、キーを確認するときと、キーを追加して追加するときに、別の何かが発生し、例外が発生する可能性があります。あなたが行っているロックはそれを行うのに十分です (Enter と Exit への追加の呼び出しは必要ありません-ロックがそれを行います)。

于 2012-07-23T20:18:44.003 に答える