我在C#中遇到了一个锁问题(但无论语言如何,这都是算法问题)。
当我输入一个方法时,我对一个对象进行读锁定。但是如果给定的对象为null(未初始化),我需要初始化它。所以,我需要对它进行写锁定。但是,问题是我已经处于读取锁定区域。
例如:
public string LocalUid
{
get
{
using (new ReadLock(MongoDBConnector.adminLock))
{
MongoClient mongo = MongoDBConnector.GetAdminClient();
// Do something...
}
}
return localUid;
}
return null;
}
}
并且GetAdminClient方法是:
public static MongoClient GetAdminClient()
{
if (adminClient == null)
{
using (new WriteLock(adminLock))
{
if (adminClient == null) // Double check locking pattern
{
adminClient = CreateAdminClient();
}
}
}
return adminClient;
}
因此我们清楚地看到在一个解锁区域中询问了writelock :(
这种情况的任何想法/最佳做法?
答案 0 :(得分:1)
这是一种称为锁定升级的常见模式。您必须非常小心,以避免因锁升级导致的死锁:
Thread A acquires read lock on Resource X.
Thread B acquires read lock on Resource X (this is allowed because Thread A only has a read lock).
Thread A wants to escalate its read lock to a write lock on Resource X, but it has to wait for Thread B to first release its read lock.
Thread B wants to escalate its read lock to a write lock on Resource X, but it has to wait for Thread A to first release its read lock.
Threads A and B are now deadlocked.
这种类型的死锁可以通过开始写入锁来避免,即,如果读取结果可能要求您稍后进行写锁定,则在读取时执行写锁定。