Hlavní navigace

Programování pod Linuxem pro všechny (12)

Jakub Matys

Dnes si povíme něco málo o předávání dat do vláken, spojování vláken a návratových kódech vláken.

Předávání dat do vlákna

Pomocí čtvrtého argumentu funkce pthread_create() lze předávat data do vlákna. Protože je typ argumentu void *, nemůžete předat do vlákna velké množství dat přímo prostřednictvím argumentu vlákna. Můžete však předat do vlákna datovou strukturu nebo pole dat. Nejčastěji se pro každé vlákno vytváří speciální datová struktura obsahující data, která vlákno očekává. Protože se předávání dat do vlákna vyřešilo takto univerzálně, můžete použít stejnou funkci pro několik vláken. Pak každé vlákno realizuje tentýž kód, ale s různými daty.

Program příkladu je podobný programům v předchozím dílu. Tento program vytvoří dvě nová vlákna. Tato vlákna budou tisknout znaky x a o, ale vytisknou jich pouze určitý počet a potom se ukončí. Obě vlákna používají stejnou funkci, avšak každé přijímá jiná data.

#include <pthread.h>
#include <stdio.h>

/* Struktura, ktera bude predavana vlaknum */
struct char_print_params
{
  /* Znak k tisknuti */
  char character;
  /* Pocet vytisknuti znaku */
  int count;
};

/* Tiskne znaky do stderr, data ziskava
   z argumentu PARAMETERS, ktery je ukazatel
   a strukturu char_print_params */

void *char_print(void *parameters)
{
  /* Nastavi ukazatel p na strukturu char_print_params */
  struct char_print_params *p = (struct char_print_params *) parameters;
  int i;

  for(i = 0; i < p->count; ++i)
    fputc(p->character, stderr);
  return NULL;
}

int main()
{
  pthread_t thread1_id;
  pthread_t thread2_id;
  struct char_print_params thread1_args;
  struct char_print_params thread2_args;

  /* Vytvori nove vlakno, ktere vytiskne
     30 000 krat pismeno x */
  thread1_args.character = 'x';
  thread1_args.count = 30000;
  pthread_create(&thread1_id, NULL, &char_print, &thread1_args);

  /* Vytvori nove vlakno, ktere vytiskne
     20 000 krat pismeno o */
  thread2_args.character = 'o';
  thread2_args.count = 20000;
  pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

  return(0);
} 

Pozor!!! Výše uvedený program obsahuje závažnou chybu. Hlavní vlákno (to, ve kterém běží funkce main()) vytváří struktury pro předání parametrů (thread1_args a thread2_args) jako lokální proměnnou a pak ukazatel na tyto struktury předává jako parametr vláknům, která vytváří. Může se stát, že systém ukončí hlavní vlákno před ukončením podřízených vláken. Pokud se tak stane, paměť obsahující struktury pro paramenty se dealokuje, zatímco zbývající dvě vlákna ji budou používat.

Spojování vláken

Jedním možným řešením je, že se hlavní vlákno donutí počkat, až zbývající vlákna skončí. Proto potřebujeme podobnou funkci, jako je wait(), která čeká, až se ukončí podřízený proces. Touto funkcí je pthread_join() a má dva argumenty – identifikační číslo vlákna, na které má čekat, a ukazatel na proměnnou typu void *, které bude přiřazen návratový kód vlákna. Pokud vás nezajímá návratový kód, zadejte hodnutu NULL.

Následující příklad ukazuje opravenou funkci main().

int main()
{
  pthread_t thread1_id;
  pthread_t thread2_id;
  struct char_print_params thread1_args;
  struct char_print_params thread2_args;

  /* Vytvori nove vlakno, ktere vytiskne
     30 000 krat pismeno x */
  thread1_args.character = 'x';
  thread1_args.count = 30000;
  pthread_create(&thread1_id, NULL, &char_print, &thread1_args);

  /* Vytvori nove vlakno, ktere vytiskne
     20 000 krat prismeno 0 */
  thread2_args.character = 'o';
  thread2_args.count = 20000;
  pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

  /* Ceka na ukonceni prvniho vlakna */
  pthread_join(thread1_id, NULL);
  /* Ceka na ukonceni druheho vlakna */
  pthread_join(thread2_id, NULL);

  return(0);
} 

Návratové kódy vláken

Pokud je druhý argument předávaný funkci pthread_join() nenulový, bude po ukončení vlákna obsahovat jeho návratový kód. Návratový kód je typu void *. Pokud chcete předat zpět jako návratový kód data nějakého datového typu (např. int, float, char), musíte tato data přetypovat na typ void *.

To by bylo pro dnešek vše, v příštím dílu si povíme něco o identifikačních číslech vláken, atributech vláken a rušení vláken.

Našli jste v článku chybu?

24. 8. 2005 13:09

Drobná chybička se vloudila. V posledni smyčce by mělo být:

    while( thread1_args.ret==0 || thread2_args.ret==0){
        wait(100);
    }

Takto se bude čekat na ukončení obou vláken.

24. 8. 2005 12:57

Dobrý den,
sice tento příspěvěk zasílám poměrně dlouho po uvěřejnění článku, přesto si myslím, že by mohl být užitečný, jelikož příklad vícevkláknového programu ve článku skutečně obsahuje drobnou chybu.

Pozn.: zkoušel jsem příklad s drobnou modifikací, kdy jsem vypisoval celý řetězec a nikoliv pouze jeden znak.

Chyba spočívala v tom, že program nezačal nic vypisovat a ihned se ukončil. To lze elegantně obejít tím, že do struktury přidáme další prvek ret:


Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Podnikatel.cz: Změny v cestovních náhradách 2017

Změny v cestovních náhradách 2017

DigiZone.cz: TV Philips a Android verze 6.0

TV Philips a Android verze 6.0

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Měšec.cz: Jak levně odeslat balík přímo z domu?

Jak levně odeslat balík přímo z domu?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Podnikatel.cz: Snížení DPH na 15 % se netýká všech

Snížení DPH na 15 % se netýká všech

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?