我在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/

10-13 01:37