Watki w C
Po tym jak napisalismy i uruchomilismy nasz programik helloworld, mozemy teraz przejsc do bardziej ciekawych rzeczy. Na rozgrzewke proponuje pare watkow. Naszymi bohaterami beda, zbieracze zbierajacy ziarno z pola i znoszacy je do spichlerza.
Czym jest watek? Nie wiem jak w innych systemach, ale w unixach jest to proces, wykonywany w watku glownym, ktory jest procesem
. Dobrze, jak juz wiemy co to jest watek to przejdziemy dalej.
Tworzymy plik programu
czlowiek@maszyna:~$ nano seeds.c
Dolaczamy pliki naglowkowe
#include <stdio.h> #include <string.h> #include <pthread.h>
Tworzymy globalne przechowywacze oraz strukture wlasciwosci zbieracza
int grain; // ziarno na polu int granary; // ziarno w spichlerzu // struktura wlasciwosci zbieracza struct collector { char name[32]; // nazwa zbieracza int seeds; // ilosc zebranych ziaren int performance; // wydajnosc };
I funkcje watku zbieracza – bedzie wywolywana podczas kazdego utworzenia
void* collect_seeds (void* collector_data) { // pobranie danych zbieracza struct collector *data; data = (struct collector *) collector_data; // zebranie ziarna int collected; collected = data->performance; if (collected <= grain) { grain = grain - collected; } else { collected = grain; grain = 0; } // aktualizacja danych zbieracza data->seeds = data->seeds + collected; printf ("%s zebral %i\n", data->name, collected); // zwrocenie ilosci zebranych ziaren return (void*) collected; }
A teraz watek glowny
int main (int argc, char *argv[]) { // ustalenie ilosci ziarna if (argc == 2 && atoi(argv[1]) > 0) { grain = atoi(argv[1]); } if (grain == 0) grain = 1000; granary = 1; // nie wymietli wszystkiego ; ) // mieszadlo liczb losowych srand (time (0)); // ustalanie danych zbieraczy struct collector collector1; strncpy (collector1.name, "Dziwigor", sizeof (collector1.name) - 1); collector1.seeds = 0; collector1.performance = rand() % 10 + 1; // losowanie wydajnosci struct collector collector2; strncpy (collector2.name, "Niesiebud", sizeof (collector2.name) - 1); collector2.seeds = 0; collector2.performance = rand() % 10 + 1; printf ("Ziarno na polu: %i ziaren\n", grain); printf ("Ziarno w spichlerzu: %i ziaren\n", granary); printf ("Zaczely sie zniwa\n\n"); int collected_seeds; // wskazniki do watkow zbieraczy pthread_t thread1; pthread_t thread2; // petelka dopoki nie zostanie zebrane cale ziarno while (grain > 0) {
Do tej pory luzik wszystko wiadomo, tworzenie i ustalanie wartosci zmiennych, no i teraz dochodzimy do najwazniejszego elementu programiku – wyzwalanie watkow
Utworzenie watku
// utworzenie watku Dziwigora pthread_create (&thread1, NULL, collect_seeds, (void*)&collector1);
Pobranie danych z watku
// pobranie zebranych ziaren pthread_join (thread1, (void*) &collected_seeds);
“Przesypanie” ziarna do spichlerza, i tak w kolko, dopoki ludki nie zbiora wszystkiego
// aktualizacja spichlerza granary = granary + collected_seeds; pthread_create (&thread2, NULL, (void*) collect_seeds, (void*)&collector2); pthread_join (thread1, (void*) &collected_seeds); granary = granary + collected_seeds; printf ("Pozostalo: %i ziaren\n", grain); } printf ("\nZniwa zakonczone\n"); printf ("%s zebral %i\n", collector1.name, collector1.seeds); printf ("%s zebral %i\n", collector2.name, collector2.seeds); printf ("Ziarno na polu: %i ziaren\n", grain); printf ("Ziarno w spichlerzu: %i ziaren\n", granary); }
Jezeli skonczylismy pisac kod, to kompilujemy programik
czlowiek@maszyna:~$ gcc -o seeds seeds.c -pthread
za pomoca parametru -pthread informujemy kompilator aby dolaczyl obpowiednie biblioteki, jak tego nie zrobimy to sofcik oczywiscie nie skompiluje sie.
Uruchamiamy programik
czlowiek@maszyna:~$ ./seeds 100
Ziarno na polu: 100 ziaren
Ziarno w spichlerzu: 1 ziaren
Zaczely sie zniwa
Dziwigor zebral 5
Niesiebud zebral 6
Pozostalo: 89 ziaren
Dziwigor zebral 5
Niesiebud zebral 6
Pozostalo: 78 ziaren
...
Dziwigor zebral 5
Niesiebud zebral 6
Pozostalo: 1 ziaren
Dziwigor zebral 1
Niesiebud zebral 0
Pozostalo: 0 ziaren
Zniwa zakonczone
Dziwigor zebral 46
Niesiebud zebral 54
Ziarno na polu: 0 ziaren
Ziarno w spichlerzu: 101 ziaren
Gdy widzimy cos podobnego to odnieslismy kolejny sukces
.
Tutaj wersja dla niecierpliwych:
Pobierz zrodlo i/lub binarke
