4

分区是我创建的一个小类。我有数千个分区驻留在名为 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

如果其他线程不使用分区对象上的锁,我不明白为什么其他线程无法访问该分区。换句话说,任何其他线程正在执行: Partitions[partNo]能够访问分区,除非它也在执行:

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

澄清:

锁只会阻止其他尝试锁定同一对象的线程。它不会阻止不尝试锁定对象的线程的访问。

要解决这种情况,您可以使用一个事件来阻止其他线程访问分区对象,并在开始序列化之前设置此事件并重新设置它,或者在处理它时从 ConcurrentDictionary 中删除对象,然后再将其放回。正是适合您的需求。

于 2013-02-07T14:32:06.283 回答