2011-02-10 15 views
10
string Get(string key){ 
    lock(_sync){ 
    // DoSomething 
    } 
} 

Jeśli DoSomething zależy tylko od klucza, potrzebuję blokady zależnej od klucza. Myślę, że może to być słownik z obiektami synchronizacji. Czy istnieje jakieś kompletne rozwiązanie?Jak parametr blokady według metody?

Coś jak prawdziwy przykład What is the best way to lock cache in asp.net?

+0

Skorzystaj ze współbieżnej struktury, takiej jak ConcurrentDictionary lub jeszcze lepszej, ale rzeczywistej pamięci podręcznej. Mogę zasugerować pamięć podręczną, jeśli chcesz (wspomnij moje imię z @ przed komentarzem). –

Odpowiedz

21

Cóż, można utworzyć Dictionary<string, object> leniwie i wypełnić go z obiektami do blokady. Na przykład:

readonly Dictionary<string, object> dictionary = new Dictionary<string, object>(); 
readonly object dictionaryLock = new object(); 

string Get(string key) { 
    object bodyLock; 
    lock (dictionaryLock) { 
     if (!dictionary.TryGetValue(key, out bodyLock)) { 
      bodyLock = new object(); 
      dictionary[key] = bodyLock; 
     } 
    } 
    lock (bodyLock) { 
     ... 
    } 
} 

Jeśli trzeba zablokować w taki sam sposób, w innym miejscu, to bym przenieść „znalezienie lock” część do metody pomocnika. Zauważ, że jeśli używasz .NET 4, ConcurrentDictionary może to ułatwić i bez użycia dodatkowego zamka.

Zauważ, że nie ma nic, co kiedykolwiek będzie miało wyczyścić słownika w tym projekcie ... czy masz ustalony zestaw kluczy (w tym przypadku jest to w porządku) czy może on rosnąć na zawsze?

Jedna rzecz, którą zdajesz sobie już uświadomić: zablokowanie samego klucza byłoby naprawdę złym pomysłem. Klucze równe mogą być wyrazistymi obiektami, a jeśli istnieje inny kod inny kod, który również blokuje ciągi znaków, może to kolidować z tym kodem. Blokowanie ciągów jest prawie zawsze błędne :)

+0

Czy zmienna 'locks' zadeklarowana na linii 1 nie powinna być" słownikiem "dla reszty bloku kodu, aby miała sens? – maxp

+0

@maxp: Tak. Naprawię. –

+0

@JonSkeet Czy rozwiązaniem jest 'ConcurrentDictionary' do wywołania' GetOrAdd' z fabryką wartości, aby wygenerować nowy obiekt blokady, jeśli klucz nie istnieje? –

Powiązane problemy