3

次のクラスがあるとします。

public class IntBagWithLock
{
    private readonly lockObject = new object();
    private bool assigned = false;
    private int data1;
    private int data2;

    public int? Data1
    {
        get { lock (lockObject) { return assigned ? data1 : (int?)null; } }
    }
    public int? Data2
    {
        get { lock (lockObject) { return assigned ? data2 : (int?)null; } }
    }
    public bool Assigned { get { lock(lockObject) { return assigned; } }

    public bool TrySetData(int value1, int value2)
    {
        lock (lockObject)
        {
            if (assigned) return false;

            data1 = value1;
            data2 = value2;
            assigned = true;
            return true;
        }
    }

    public bool IsEquivalentTo(IntBagWithLock other)
    {
        if (ReferenceEquals(this, other)) return true;
        if (ReferenceEquals(other, null)) return false;

        lock (lockObject)
        {
            if (!assigned) return false;
            lock (other.lockObject)
            {
                return other.assigned && other.data1 == data1 && other.data2 == data2;
            }
        }
    }
}

ここで私が心配している問題は、スレッドが呼び出されて取得されたのロックと、別のスレッドが呼び出されて取得IsEquivalentToされた場合、実装方法が原因でデッドロック状態になる可能性があることです。item1.IsEquivalentTo(item2)item1item2.IsEquivalentTo(item1)item2

このようなデッドロックが発生しないようにするには、どうすればよいですか?

更新 2 : コード サンプルは、私が実際に持っているものに近づくように変更されました。すべての答えはまだ有効だと思います。

4

4 に答える 4

1

get または equal するたびにロックする理由はわかりませんが、次のことができます。

public bool IsEquivalentTo(BagWithLock other)
{
    object myData;
    object otherData;
    lock (lockObject)
        myData = data;

    lock (other.lockObject)
        otherData = other.data;

    return object.Equals(myData, otherData);
}

そうすれば、比較中に項目が変化しません。

lockObject一般に、この種のロックにはいくつかの欠点があります。競合状態になる可能性のあるメソッドで一度にオブジェクトのみを持つことができるように、一般的な静的を実行したと思います


あなたのアップデート によると、私はあなたが使用すべきだと言います:

private static readonly object equalLock = new object();

public bool IsEquivalentTo(IntBagWithLock other)
{
    lock(equalLock){
       if (ReferenceEquals(this, other)) return true;
       if (ReferenceEquals(other, null)) return false;
         if (!assigned) return false;
           return other.assigned && other.data1 == data1 && other.data2 == data2;
   }
}
于 2013-08-20T10:20:08.230 に答える
0

おそらく、よりコストのかかる派生のWaitHandleロック オブジェクト ( Mutexなど) を使用WaitHandle.WaitAll()して、一度に複数のロックが必要な場合に使用できますか?

于 2013-08-20T10:20:27.993 に答える