ConcurrentDictionary - Wielowątkowy dostęp

0

Witam,

Mam taką zagwozdkę: testowałem ostatnio ConcurrentDictionary (http://msdn.microsoft.com/en-us/library/dd287191.aspx) pod Windowsem i pod Mono
I taki oto kod:

   class MojObiekt
   {
       int stan;
       public int Stan { get { return stan; } }
       public void Dodaj() { stan++; }
       public void Odejmij() { stan--; }
   }

   class Program
   {
       const int Max = 10000;
       const string Klucz = "klucz";

       static ConcurrentDictionary<string, MojObiekt> slownik;

       static void Dodawaj()
       {
           int i = 0;
           while (i++ < Max)
               slownik[Klucz].Dodaj();
       }

       static void Odejmuj()
       {
           int i = 0;
           while (i++ < Max)
               slownik[Klucz].Odejmij();
       }

       static void Main(string[] args)
       {
           slownik = new ConcurrentDictionary<string, MojObiekt>();
           slownik.AddOrUpdate(Klucz, new MojObiekt(), (key, value) => new MojObiekt());

           Thread dodawator = new Thread(Dodawaj);
           Thread odejmowator = new Thread(Odejmuj);
           dodawator.Start();
           odejmowator.Start();
           dodawator.Join();
           odejmowator.Join();
           Console.WriteLine(slownik[Klucz].Stan);
       }
   }

zarówno pod Windowsem jak i pod Mono daje wynik inny niż 0.
A z tego co pisze na stronie msdn ConcurrentDictionary powinno być thread-safe.
Czy ktoś wie o co chodzi?
Może źle rozumiem, co oznacza thread-safe, mimo że przeczytałem http://stackoverflow.com/questions/1949131/net-dictionary-locking-vs-concurrentdictionary

Dodam jeszcze, że w przypadku gdy zmienię:

class MojObiekt

na

struct MojObiekt

wszystko jest ok, pod Windowsem i pod Mono wyświetla 0. Domyślam się, że jest tak ponieważ struktury należą do typów prostych. Ale dlaczego? I dlaczego klasy (a pewnie i w ogólności typy referencyjne) nie sprawdzają się?

1

Niestety nie mam frameworka w wersji 4.0 więc nie potestuje...

Mi podejrzanie wygląda lambda tutaj: slownik.AddOrUpdate(Klucz, new MojObiekt(), (key, value) => new MojObiekt());
Powinna, jeśli rozumiem dokumentację, zwracać nowy obiekt o podanej wartości - a zwraca pusty obiekt. Może spróbuj dopisać konstruktor do MojObiektu i zamienić ją na new MojObiekt(value).

(Pytanie, czy to tłumaczy czemu przy strukturach jest zero - możliwe że przy klasach są dwie referencje na różne obiekty osobno modyfikowane, a przy strukturach wynik to po prostu... dziewicza, niemodyfikowana instancja MojObiekt. Ofc możliwe że się mylę bo tak jak pisałem, nie potestuje sobię...)

0

Wydaje mi się, że problem nie leży tutaj:

 slownik.AddOrUpdate(Klucz, new MojObiekt(), (key, value) => new MojObiekt()); 

gdyż jeśli zamiast tego fragmentu kodu użyjemy:

 slownik.TryAdd(Klucz, new MojObiekt()); 

To nic się nie zmienia. Więc problem na pewno nie leży w wyrażeniu lambda.

Problemem jest raczej dokładne zrozumienie znaczenia słowa thread-safe dla ConcurrentDictionary.

0

Oto coś co rzuci nieco światła na całą tą sprawę z thread-safe:
http://msdn.microsoft.com/en-us/library/dd997369.aspx

1 użytkowników online, w tym zalogowanych: 0, gości: 1