Czekanie wątku rodzica za dziećmi + Mutex

0

Hej, mam generalnie taki kodzik na którym mam porównać wielowątkowe sumowanie tablicy vs sekwencyjne. Tylko mam problem z pomiarem czasu. Generalnie kiedy dam Join() na wątek rodzica to mimo to kod z rodzica się kończy i finito, mimo że wątki dzieci pracują. Prosiłbym o radę i jeszcze o sprawdzenie czy prawidłowo zastosowałem Mutex. Generalnie chciałem zastosować jakąś funkcję sprawdzającą w pętli while, ale to znacznie opóźni działanie programu.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;


namespace mutex
{
    class Program
    {
        static private Mutex mutx = new Mutex(false, "nazwa_mutexa");

        static private int suma_mutex = 0;
        //static bool end = false;

        static int[] tablica = new int[1000000];


        static void Main(string[] args)
        {
            //tworzenie i uzupełnienie tablicy
            for (int i = 0; i < 1000000; i++)
            {
                tablica[i] = 1;
            }

            Thread t1 = new Thread(
            () => { suma_tablicy(tablica);
            });

            DateTime startTime = DateTime.Now;// wczytanie wartosci poczatkowej

            t1.Start();
            t1.Join();

            Console.WriteLine(suma_mutex);

            DateTime stopTime = DateTime.Now;   //wczytanie wartosci koncowej
            TimeSpan roznica = stopTime - startTime;    // obliczenie czasu wykonania
            Console.WriteLine("Czas wykonania " + roznica.TotalMilliseconds + "ms");   // wypisanie czasu wykoania

            Console.ReadKey();



        }


        static void suma_tablicy(int[] tab)
        {
            Thread pierwszy =new Thread(() =>
            {
                for (int i = 0; i < 333333; i +=1)
                {
                    mutx.WaitOne();     //mutex on
                    suma_mutex += tab[i];
                    mutx.ReleaseMutex();
                 //   Console.WriteLine("Pierwszy");
                }

            });

            Thread drugi = new Thread(() =>
              {
                  for (int i = 333333; i < 666666; i += 1)
                  {
                          mutx.WaitOne();
                          suma_mutex += tab[i];
                          mutx.ReleaseMutex();
                      //    Console.WriteLine("Drugi");
                  }
              });

            Thread trzeci = new Thread(() =>
            {
                for (int i = 666666; i< 1000000; i++)
                {
                        mutx.WaitOne();
                        suma_mutex += tab[i];
                        mutx.ReleaseMutex();
                    
                   // Console.WriteLine("Trzeci");
                }
                Console.WriteLine(suma_mutex);
                
            });

            pierwszy.Start();
            drugi.Start();
            trzeci.Start();

        }


    }
}

0

Ojej, ojej, ojej, a czytałeś cokolwiek o programowaniu równoległym w C#?
Do mierzania czasu używa się klasy Stopwatch, nie DateTime ...
mutexy służą do synchronizacji między procesowej, a nie w obrębie jednego procesu,
wątków się już bardzo rzadko używa, bo jest lepsza abstrakcja w postaci TPL... a tam masz klasę Parallel i Taski,
no ale wracając do twojego kodu to wypadałoby by poczekać na trzy wątki dzieci, tak samo jak to robisz z wątkiem rodzica,
i nie potrzebujesz w ogóle synchronizacji w tym problemie,
niech każdy wątek policzy swoją część tablicy w oddzielnej zmiennej, a potem zsumuj wyniki.

A najprościej to w ogóle użyć PLINQ

tablica.AsParallel().Sum();
0

Generalnie rzecz biorąc wiem że najbardziej da się to uprościć do iteracyjnego zsumowania.... i będzie najszybciej, ale nie takie jest założenie jak pisałem. Problem w tym, że jeżeli czekam za wątkami dziećmi to wykonują się one sekwencyjnie.

0

Prawdopodobnie wystarczyłoby Ci volatile w definicji pola.

2)Najlepsze rozwiazanie:
Przy samym dodwaniu absolutnie nie masz potrzeby używania synchornizacji ręcznie.
W przestrzeni System.Threading masz Interlocked.Increment i przekazując referencje do zmiennej (ref) i wartosc.
Czesto na technicznej rozmowie o pracy o to pytam nie moge wyjsc z podziwnu jak 95% majstruje z mutexami/semaforami/lockami.

3)Rozwiazanie dobre -> monior.
Zamiast mutexa ktory jest ogolnie systemowy (C# to wrapper na WinAPI) uzyj Monitora który dziala chyba na domenie aplikacji.
lock(takis obiekt referencyjny)counter++;
Fajnie mozna nim operować.
Można okreslić jak dlugo monitor bedzie probowal pozyskac zasob referencyjny.
Można fajnie uzywac Pulse, PulseAll, Wait.

Uwaga: uczac sie go zwroc uwage na wersje .netu. Nastapiła zmiana w umiejscowieniu monitora z try catch blokiem.

Fajnym moniotorem jest ReadWriterLock -> klasyczny przyklad czytelnicy i pisarz.

  1. To prawda ze odchodzi ze od watkow, jednkze nie sadze aby to nastapilo w 100%.
    Nawet w nowych projektach nadal się ich wykorzystuje (ktore dlugo (nie sekundy) coś miela w tle) jezeli wazne jest by miec kontrole nad praca watku (stany Stop oraz wazny Wait/Sleep/Join).
    Bardzo często w IT -> im wiecej wygodny tym mniej kontroli i vice vesra (np uwierzytelnianie dwustopniowe, czy reczne kontrola pamieci new/delete, wydajniejsze albo mozliwe bledy i uciążliwe).
    Cos za coś.

Jedna z przyczyn i zachęt stosowania Tasków bylo np nieumiejetne korzystanie z funkcji Abort() oraz Interupt().
Powstawały memoryleaki (tak, nawet w C# !), niezwalniane zasoby z presja pamięci i niezwalniane blokady systemowe np w polączeniu z Interoperability.

Bardzo dobrze znać watki gdyż głowne zasady i mechnizmy ich synchronizacji/sterowania wystepuja w bardzo wielu jezykach programowania.
Tak jak idea procesu jest ponad systemowa i ponad jezykowa, tak z wątkiem jest podobnie.

  1. Uczac sie, zapoznaj sie z 2-3 roznicami miedzy mutexem a semaforem.
    Ludzie w CV wpisuja "znajomosc programowania wspolbierznego" a na prostym sie wykladaja :)

P

0

Wreszcie jakaś sensowna odpowiedź. Dzięki za rady.
Generalnie robię takie drobne zadanka z programowania współbieżnego na studia i niestety na nieszczęście niektórych użytkowników tego forum wykorzystują one wątki w czystym tego słowa znaczeniu w celu przedstawienia problemów hazardu, czytelników i pisarzy itd. Generalnie ten Mutex w tym przypadku skutecznie hamuje program i lepiej byłoby agregować dane do jakiejś chwilowej zmiennej, ale tutaj chodzi o pokazanie, że synchronizacja trochę kosztuje.

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