[C#] Wielowątkowość a dostęp do wspólnych danych

Witam

Mam napisać program wielowątkowy, w sumie już go napisałem jednak pojawia się problem. Dzielę dane na porcje. Następnie je przetwarzam i zapisuje wyniki do wspólnej tabeli z wynikami. Jak wygląda od środka taki zapis? Ponieważ wyniki dla 1 wątku, 2,3 itd się różnią. Nie jest tak że jeśli dwa wątki na raz chcą wykonać tablica[5]++ to jeden z nich nie dostaje dostępu ?

Jednoczesne operowanie kilku wątków na jednej tablicy może mieć nieciekawe skutki. Inne platformy mają jakieś mechanizmy rywalizacji wątków, więc pewnie ma je i .NET. Jednak żeby lepiej nad tym zapanować użyj Mutexów albo innych Monitorów:

http://www.altcontroldelete.pl/artykuly … or-mutex-/

Zrobiłem prosty test. 500 wątków a w każdym wątku zwykła pętla wykonująca się 10000 razy i jedyne co robi to ilosc++; Matematyka jest prosta.

500 * 10000 = 5 000 000 a program wypluł 4 850 547. Czyli nie wolno tak robić.

:arrow: http://en.wikipedia.org/wiki/Race_condition

Aktualnie mam tak ze tworze listę tablic do których kazdy wątek będzie zapisywał wyniki ze swojej porcji danych. Do watku przesyłam dane i numer watku tak żeby wiedzial do której tablicy w liście sie odwołać a na końcu lacze wyniki ze wszystkich tablic. Sprawdzałem i działa jak należy.

Jeśli to ma być zwykła inkrementacja wartości, to należy używać tzw. atomiców. Tego typu funkcje mają zazwyczaj w nazwie słówko “interlocked” i ich charakterystyczną cechą jest właśnie odporność na hazardy. Pewnie w .NET też coś takiego jest. Jeżeli natomiast wątki ciągle wymieniają się danymi, tzn. każdy wątek zapisuje i odczutuje dowolne elementy całej tablicy, to musisz to przemyśleć. Można zrobić tak, że na czas zapisu/odczytu lockujesz tę tablicę (słówko kluczowe “lock”) ale może się okazać, że program będzie się wtedy wykonywał dłużej niż jego jednowątkowy odpowiednik.

@Marcin511

Bardzo “enigmatycznie” przedstawiasz swój problem. Zaprezentuj fragment kodu źródłowego, w którym - według Ciebie - tkwił błąd, a wtedy na pewno znajdziemy wspólny język.

Bo każdy kto programował wielowątkowo wie o co chodzi :wink:

int ilosc=0;

int ilosc_watkow=500;

List watki = new List()

void funkcja_watku()

{

    for(int i=0;i<10000;i++)

        ilosc++;

}

void funkcja_start()

{

    for(int i=0;i
    {

        watki.Add(new Thread(funkcja_watku));

        watki[i].Start();

    }

}

Po wykonaniu się tego kodu ilość powinna być 5 000 000 a jest ~4 800 000. Ktoś wyżej dawał ciekawy link. Ja póki co mam zrobione w sposób prosty gdzie każdy wątek zapisuje wyniki do swojej listy i na końcu listy są łączone.

@Marcin511

No widzisz, takie operacje jak ilosc++ w środowisku wielowątkowym powinieneś wykonywać z goła inaczej. Masz bardzo wiele możliwości poprawienia swojego kodu. Niektóre z dostępnych możliwości to:

  • wykorzystaj słowo kluczowe lock i wskaż wspólny dla wszystkich wątków obiekt (readonly object obj = new object()), do którego dostęp będziesz każdorazowo blokował w danym wątku przed wykonaniem inkrementacji na zmiennej “ilosc”.

  • wykorzystaj klasę Interlocked i metodę Increment

  • wykorzystaj słowo kluczowe volatile na globalnej zmiennej “ilosc”

To są bardzo podstawowe mechanizmy, a ułatwią Tobie znacznie pracę.

Z drugiej strony, kiedy wyświetlasz wartość zmiennej “ilosc”? Skąd wiesz, że wszystkie wątki zakończyły pracę? Prawdopodobnie wyświetlasz zawartość zmiennej w chwili kiedy jest ona jeszcze przedmiotem pracy w tle… -> poczytaj o Thread.Join i podobnych zagadnieniach.

Pozdrawiam

Mam też bardzo łopatologiczny sposób na to :slight_smile: Wiadomo każdy się uczy i kombinuje. Ja wykombinowałem tak że znowu każdy wątek zapisuje true że się skończył. Dodatkowy wątek ma pętle While(true) i sprawa czy każdy wątek zapisał true. Jeśli tak to dopiero wyświetlam. Ale wiadomo z wątkami miałem do czynienia ale tylko w taki sposób że jest jeden wątek tak aby forma nie sprawiała wrażenia że się zawiesiła. Teraz na studiach weszło programowanie współbieżne więc muszę się bardziej zagłębić w wątki.

@Marcin511

Brawo, dajesz sobie radę, ale taką samą informację uzyskasz z pola Thread.IsAlive (żyjesz? jeżeli nie, to albo zakończyłeś obliczenia, albo anulowałem twoją pracę) :wink:

Jak zwykle, najlepszym źródłem wiedzy jest MSDN, ale bardzo dobrą lekturą jest także:

http://www.albahari.com/threading/

Mam też książkę http://ksiegarnia.pwn.pl/produkt/104381 … et-40.html i szukam też czegoś do Windows Phone SDK bo muszę napisać pewną aplikację na Windows Phone na pracę inżynierską. Ale to inny temat

Można i tak, ale z doświadczenia powiem Ci, że bardziej opłaca się nie kombinować, tylko przeczytać jak coś działa i zacząć nową wiedzę stosować w praktyce. :slight_smile:

Ja jestem taki że najpierw kombinuje sam a później szukam jak nie umiem :wink: