Synchroniczność w liczniku

0

Witajcie,

Otóż miałem wykonać zadanie gdzie otwieramy 3 wątki, w którym każdy będzie zwiększał licznik o 10. Wykonałem to tak:

            SimpleCounter counter = new SimpleCounter();
            Console.WriteLine("Startowa wartość: " + counter.val);
            Thread.Sleep(2000);
            Console.WriteLine("Ruszam...");
            Thread t1 = new Thread(run);    // run to metoda, która zwiększa licznik 10x
            Thread t2 = new Thread(run);
            Thread t3 = new Thread(run);
            t1.Start(counter);     // counter to nasz licznik
            t2.Start(counter);
            t3.Start(counter);
            try
            {
                t1.Join();
                t2.Join();
                t3.Join();
            }
            catch (ThreadInterruptedException e)
            {
                Console.WriteLine("Interrupted" + e);
            }
            Console.WriteLine("Finalna wartość: " + counter.val);

Z tym, że przy większych powtórzeniach np. 10000, pojawią się błędy i różne wyniki. Wiem, że mogę to obejść asynchronicznością ale jak?

Tu metoda w liczniku, która go zwiększa:

            public void inc()
            {
                 val++; 
            }

Tu zaś nasza metoda run:

         public void run(object obj1)
            {
             SimpleCounter obj = (SimpleCounter)obj1;
             for (int i = 0; i < 1000; i++)
                {
                    obj.inc();
                }
            }

Pytanie dla osób, które znają temat asynchroniczności banalne jednak sprawa mi trochę problemów :/
Pozdrawiam

0

Oj ja tu coś powinienem zrobić z Lock ? Nie mylę się?

2

To nie ma nic wspólnego z asynchronicznością, tylko z jednoczesnym dostępem do tego samego obszaru pamięci aka sekcja krytyczna. Najprościej uźyc locka do synchronizacji:

class SimpleCounter 
{
   private readonly object lockInc  = new Object();

   public void inc()
   {
       lock(lockInc)
       {               
           val++;
       } 
    }
}

albo atomowej operacji:

public void inc()
{
    Interlocked.Increment(ref val);
}

a najlepiej to by było pozbyć się wspódzielonej pamieci, i liczyc odzielnie a na końcu zsumować wyniki, ale to pewnie nie jest cel tego zadania ;)

0

Oko dziękuję ;)

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