This is an old revision of the document!


Laboratorul 5 - pthreads

Despre pthreads

pthreads reprezintă o bibliotecă din C/C++, nativă Linux, prin care se pot implementa programe multithreaded.

Spre deosebire de OpenMP, pthreads este low-level și oferă o mai mare flexibilitate în ceea ce privește sincronizarea thread-urilor și distribuirea task-urilor către thread-uri.

Implementarea unui program paralel în pthreads

Includere și compilare

Pentru a putea folosi pthreads, este necesar să includem în program biblioteca pthread.h. De asemenea la compilare este necesar să includem flag-ul -lpthread:

gcc -o program program.c -lpthread
./program

Crearea și terminarea thread-urilor

În pthreads, avem un thread principal, pe care rulează funcția main. Din thread-ul principal se pot crea thread-uri noi, care vor executa task-uri în paralel.

Pentru a crea thread-uri în pthreads, folosim funcția pthread_create:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*thread_function) (void *), void *arg);

unde:

  • thread - thread-ul pe care vrem să-l pornim
  • attr - atributele unui thread (NULL - atribute default)
  • thread_function - funcția pe care să o execute thread-ul
  • arg - parametrul trimis la funcția executată de thread (dacă vrem să trimitem mai mulți parametri, îi împachetăm într-un struct

Exemplu de funcție pe care o execută un thread:

void *f(void *arg) {
    // do stuff
    // aici putem să întoarcem un rezultat, dacă este cazul
    pthread_exit(NULL); // termină un thread - mereu apelat la finalul unei funcții executate de thread, dacă nu întoarcem un rezultat în funcție
}

Pentru terminarea thread-urilor, care vor fi “lipite înapoi” în thread-ul principal, folosim funcția pthread_join, care așteaptă terminarea thread-urilor:

int pthread_join(pthread_t thread, void **retval);

unde:

  • thread - thread-ul pe care îl așteptăm să termine
  • retval - valoarea de retur a funcției executate de thread (poate fi NULL)

Exemplu de program scris folosind pthreads:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
 
#define NUM_THREADS 2
 
void *f(void *arg)
{
    long id = *(long*) arg;
    printf("Hello World din thread-ul %ld!\n", id);
    return NULL;
}
 
int main(int argc, char *argv[])
{
    pthread_t threads[NUM_THREADS];
    int r;
    long id;
    void *status;
    long arguments[NUM_THREADS];
 
    for (id = 0; id < NUM_THREADS; id++) {
        arguments[id] = id;
        r = pthread_create(&threads[id], NULL, f, (void *) &arguments[id]);
 
        if (r) {
            printf("Eroare la crearea thread-ului %ld\n", id);
            exit(-1);
        }
    }
 
    for (id = 0; id < NUM_THREADS; id++) {
        r = pthread_join(threads[id], &status);
 
        if (r) {
            printf("Eroare la asteptarea thread-ului %ld\n", id);
            exit(-1);
        }
    }
 
    return 0;
}

În caz că dorim să trimitem mai mulți parametri funcției executate de threads, folosim un struct, în care incapsulăm datele, și îl trimitem ca parametru al funcției executate de threads.

Exemplu:

Click pentru exemplu

Click pentru exemplu

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
 
#define NUM_THREADS 8
 
struct pair {
    int first, second;
};
 
void *f(void *arg)
{
    struct pair info = *(struct pair*) arg;
    printf("First = %d; second = %d\n", info.first, info.second);
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[])
{
    pthread_t threads[NUM_THREADS];
    int r;
    long id;
    void *status;
    struct pair arguments[NUM_THREADS];
 
    for (id = 0; id < NUM_THREADS; id++) {
        arguments[id].first = id;
        arguments[id].second = id * 2;
        r = pthread_create(&threads[id], NULL, f, (void *) &arguments[id]);
 
        if (r) {
            printf("Eroare la crearea thread-ului %ld\n", id);
            exit(-1);
        }
    }
 
    for (id = 0; id < NUM_THREADS; id++) {
        r = pthread_join(threads[id], &status);
 
        if (r) {
            printf("Eroare la asteptarea thread-ului %ld\n", id);
            exit(-1);
        }
    }
 
    pthread_exit(NULL);
}
app/laboratoare/05.1666807519.txt.gz · Last modified: 2022/10/26 21:05 by florin.mihalache
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0