Pergunta

Partition is a small class I created. I have thousands of partitions that reside in a ConcurrentDictionary named Partitions. Before serialization, I want to lock a specific partition, do some work and then unlock the partition.

During this time no other threads should be able to access that Partition. Since my class Partition is a reference type, I am wondering if I can lock on a single Partition object as I have in the code below?

Will this block other threads from a single Partition in the ConcurrentDictionary Partitions during the lock below?

I don't want to lock using a class level locker object. My thought process is that multiple threads should be able to run the code below at the same time. They just should not be able to access a specific partition, if it is locked...

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;
        }
    }
Foi útil?

Solução

Your current implementation will only block that Partition object at that point in the function code. Another thread will still be able to access that Partition object as long as the thread isn't executing serializePartition() again. Seeing that you are using ConcurrentDictionary, it is Thread safe so there shouldn't be a problem.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top