4

Partition は私が作成した小さなクラスです。Partitions という名前の ConcurrentDictionary に存在する何千ものパーティションがあります。シリアル化の前に、特定のパーティションをロックし、いくつかの作業を行ってから、パーティションのロックを解除したいと考えています。

この間、他のスレッドはそのパーティションにアクセスできません。私のクラス Partition は参照型であるため、以下のコードのように単一の Partition オブジェクトをロックできるかどうか疑問に思っています。

これにより、以下のロック中に ConcurrentDictionary パーティション内の単一のパーティションからの他のスレッドがブロックされますか?

クラス レベルのロッカー オブジェクトを使用してロックしたくありません。私の考えでは、複数のスレッドが以下のコードを同時に実行できるようにする必要があります。ロックされている場合、特定のパーティションにアクセスできないはずです...

private void serializePartition(int partNo)
    {
        Partition p;

        //Get a reference to the partition, lock, and save it to disk.
        lock (p = Partitions[partNo])
        {
            using (var file = File.Create(dataPath + tableName + partNo + ".ppmi"))
            {
                Serializer.Serialize(file, p);
            }

            //decrement _CurrentRecordsInMemory by the size of the partition.
            Interlocked.Add(ref _CurrentRecordsInMemory, p.Data.Count * -1);

            //Clear the partitions data to free up memory and reset partition variables
            p.Data = null;
            p.OnDisk = true;
            p.StartCount = 0;
        }
    }
4

2 に答える 2

2

現在の実装では、関数コードのその時点でそのPartitionオブジェクトのみがブロックされます。スレッドがserializePartition()を再度実行しない限り、別のスレッドは引き続きそのPartitionオブジェクトにアクセスできます。ConcurrentDictionaryを使用していることを確認すると、スレッドセーフであるため、問題は発生しません。

于 2012-10-17T02:14:22.660 に答える
0

I don't see why other threads are not able to access the partition if they are NOT also use a lock on the partition object. I other words, any other thread doing: Partitions[partNo] is able to access the partion except when it is ALSO doing:

lock (p = Partitions[partNo])
{ 
    //DO SOM STUFF ONLY WHEN YOU GOT ACCESS TO THE LOCK
}

To clarify:

An lock will only keep other threads out who ALSO try to lock the same object. It does not prevent access from threads who do not try to lock the object.

To fix this situation you could use maybe an event to block other threads from accessing the partition object and set this event before you start serializing and reset it aftwards or just remove the object from the ConcurrentDictionary while working on it and put it back afterwards. Just what suits your needs.

于 2013-02-07T14:32:06.283 に答える