2017-04-14 1 views
1

ReSharper suggère l'emballage return dic.Contains("v1"); dans un communiqué de verrouillage disant « le champ est parfois utilisé à l'intérieur bloc synchronisé et parfois utilisé sans synchronisation »:Ne vérifie pas l'existence de la clé dans un dictionnaire statique thread-safe? ReSharper pense que ce n'est pas

public class MyClass 
{ 
    private static Dictionary<string, string> _dic = new Dictionary<string, string>(); 

    protected bool V1Exist() 
    { 
     return dic.Contains("v1");    
    } 
} 

Cependant, je ne vois pas pourquoi verrouillage est nécessaire dans l'exemple. Cela semble sûr pour moi. S'il vous plaît aviser

+0

'Dictionary' en général n'est pas thread-safe. Utilisez 'ConcurrentDictionary' si vous avez besoin d'un dictionnaire à thread sécurisé. –

+0

Les dictionnaires ne sont pas thread-safe. ConcurrentDictionaries sont –

+0

Si vous écrivez et lisez un dictionnaire à partir de plusieurs threads - les deux écritures et lectures ne sont pas thread sûr – Evk

Répondre

2

Il est connu que le dictionnaire n'est pas thread-safe, vous devez donc synchroniser les écritures et les lectures. Mais si vous voulez exemple précis de ce qui peut aller mal - considérer cette petite application:

static void Main(string[] args) { 
    var dict = new Dictionary<int, int>(); 
    dict.Add(0, 0); 
    new Thread(() => { 
     for (int i = 1; i < int.MaxValue; i++) { 
      lock (dict) { 
       dict.Add(i, i); 
       dict.Remove(i); 
      } 
     } 
    }).Start(); 
    new Thread(() => { 
     while (true) { 
      if (!dict.ContainsKey(0)) 
       throw new Exception("cannot happen?"); 
     } 
    }).Start(); 
    Console.ReadKey(); 
} 

Nous créons dictionnaire avec une entrée à clé 0, nous courons deux fils. Le premier thread ajoute et supprime constamment les clés du dictionnaire, mais notez qu'il ne supprime PAS l'élément avec la clé 0. L'élément avec la clé 0 est toujours présent.

Les deuxièmes threads vérifient en permanence s'il y a un élément avec la clé 0 et lancent une exception si ce n'est pas le cas. Vous pourriez penser que cela ne peut jamais arriver, parce que nous ne supprimons jamais l'élément avec la clé 0, mais ce n'est pas vrai. Si vous allez exécuter cette application, il va lancer "ne peut pas arriver?" exception presque immédiatement. Si vous ajoutez un verrou autour de ContainsKey - cela n'arrivera jamais. Donc, en bref, les choses pourraient mal se passer si vous ne synchronisez pas l'accès à des structures qui ne sont pas sûres, même des lectures. Et vous ne remarquerez peut-être même pas cela, et vous aurez TRES mal à déboguer de tels problèmes, car l'application peut se comporter comme si tout allait bien.