我在c_中遇到了一个锁的小问题(但不管是哪种语言,它更多的是一个算法问题)。
当我输入一个方法时,我对一个对象进行读锁但如果给定的对象为空(未初始化),则需要对其进行初始化。所以,我需要一个写锁。但是,问题是我已经在读锁区了。
前任:
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是在readlocked区域中被请求的:(
对这个案子有什么想法/最佳做法吗?
最佳答案
这是一种常见的模式,称为锁升级。您必须非常小心,以避免锁升级导致的死锁:
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.
这种类型的死锁可以通过以写锁开始来避免,即,如果读取的结果可能要求您稍后获取写锁,则在读取时获取写锁。
关于c# - 正确的锁定方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48763454/