分区是我创建的一个小类。我有数千个分区驻留在名为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;
}
}
答案 0 :(得分:2)
您当前的实现只会在功能代码中阻止该位置的Partition对象。只要线程没有再次执行serializePartition(),另一个线程仍然可以访问该Partition对象。看到你正在使用ConcurrentDictionary,它是Thread安全的,所以应该没有问题。
答案 1 :(得分:0)
我不明白为什么其他线程如果不在分区对象上使用锁定则无法访问该分区。
换句话说,任何其他线程正在做:Partitions[partNo]
能够访问分区
除非它正在做的事情:
lock (p = Partitions[partNo])
{
//DO SOM STUFF ONLY WHEN YOU GOT ACCESS TO THE LOCK
}
澄清:
锁定只会保留其他线程,并尝试锁定同一个对象。它不会阻止来自不尝试锁定对象的线程的访问。
要解决这种情况,您可以使用一个事件来阻止其他线程访问分区对象并在开始序列化并重置它之前设置此事件,或者只是在处理它时将对象从ConcurrentDictionary中删除并将其放回然后。适合您的需求。