簡體   English   中英

潛在的並發問題?

[英]Potential Concurrency Issue?

我一直在構建ASP.NET MVC應用程序,當我啟動它時,我擔心潛在的多線程問題。 一個特別值得關注的是以下代碼:

private static IDictionary<string, ISettings> _settingsDictionary = new Dictionary<string, ISettings>();

public T Settings<T>() where T : ISettings, new() {
    var key = typeof(T).FullName;

    if (!_settingsDictionary.ContainsKey(key))
        _settingsDictionary[key] = _settingsService.GetSettings<T>();

    return (T)_settingsDictionary[key];
}

請注意,字典定義為靜態。 這允許我緩存字典,以便它為應用程序長度的每個請求返回相同的實例。

這在本地測試時工作正常,但我擔心它可能會被數百名用戶使用。 這讓我研究了ConcurrencyDictionary。 請問你能告訴我是否需要使用它以及如果是這樣的話我會怎么做。

謝謝

是的,這里有潛在的數據競爭:

if (!_settingsDictionary.ContainsKey(key))
    _settingsDictionary[key] = _settingsService.GetSettings<T>();

這可能導致兩個線程添加相同的密鑰,因為它們可以在任何時候中斷。

您可以使用ConcurrentDictionary.GetOrAdd代替:

private static ConcurrentDictionary<string, ISettings> _settingsDictionary = new ConcurrentDictionary<string, ISettings>();

public T Settings<T>() where T : ISettings, new() {
    var key = typeof(T).FullName;

    return _settingsDictionary.GetOrAdd(key, _settingsService.GetSettings<T>());
}

編輯 :由於您不希望每次都執行_settingsService.GetSettings<T>() ,因此可以選擇:

private static IDictionary<string, ISettings> _settingsDictionary = new Dictionary<string, ISettings>();
private static object locker = new object();

public T Settings<T>() where T : ISettings, new() {
    var key = typeof(T).FullName;
    lock(locker) 
    {
        if (!_settingsDictionary.ContainsKey(key))
            _settingsDictionary[key] = _settingsService.GetSettings<T>();

        return (T)_settingsDictionary[key];
    }
}

是的,有一場比賽,因為如果沒有找到鑰匙:

if (!_settingsDictionary.ContainsKey(key))

那時我們跑:

_settingsDictionary[key] = _settingsService.GetSettings<T>();

可能有一把鑰匙。

它甚至比不必要地更換更糟糕。 如果添加密鑰的線程1需要調整大小,那么當線程2添加並且它被認為需要調整大小時它可能是部分通過,並且幾乎所有的注意都被關閉以用於該字典的任何進一步使用。

重要的問題是,“這是一個案例,我們將有大量的線程同時擊中字典,或者這是一個罕見但我們需要防范它的情況?”

在第一種情況下,使用ConcurrentDictionary。 在第二種情況下,只需為當前代碼添加鎖定即可。 ConcurrentDictionary在並發性方面提供了更好的性能(正如人們對名稱所期望的那樣),但是當通常只有一個線程實際命中它時,圍繞普通字典的鎖定會更好,但偶爾的並發調用是可能的。

替代兩者,如果可能的設置數量很少,只需在開頭加載批次。 如果沒有更多的寫作,字典對於多個讀者是安全的,並且對於零鎖定而言,這是最快的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM