Use a Biblioteca de Threads C11 em C

Jinku Hu 12 outubro 2023
  1. Use a função thrd_create para criar um novo thread e executar a rotina fornecida em C
  2. Use a função thrd_join para esperar pelo thread fornecido em C
Use a Biblioteca de Threads C11 em C

Este artigo irá explicar vários métodos de como usar a biblioteca de threads C11 em C.

Use a função thrd_create para criar um novo thread e executar a rotina fornecida em C

O suporte ao threading já era esperado há muito tempo na especificação da linguagem C padrão e finalmente foi realizado no C11. Antes disso, a API de threads POSIX foi usada como a principal ferramenta para utilizar a programação multi-threaded. Uma vez que o C11 forneceu uma interface mais padrão que poderia ser usada sem dependências de plataforma, foi recomendado usar a API de linguagem ISO do que a versão POSIX. Embora as duas APIs não correspondam em seus protótipos de função, os principais recursos são semelhantes. No exemplo a seguir, demonstramos o cenário simples onde quatro threads são iniciados para executar a função printHello e, em seguida, terminam sem entrar no thread principal.

thrd_create leva três argumentos,

  1. O primeiro é um ponteiro para o identificador de thread.
  2. O segundo argumento é do tipo - thrd_start_t, que é apenas typedef para um protótipo de ponteiro de função.
  3. O terceiro parâmetro especifica um argumento que pode ser passado para a função.

Os códigos de status de retorno de thrd_create são definidos usando os valores enum: thrd_success, thrd_nomem e thrd_error.

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("Hello There! thread #%ld, pthread ID - %lu\n", tid, thrd_current());
  thrd_exit(EXIT_SUCCESS);
}

int main(int argc, char const *argv[]) {
  thrd_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }
  thrd_exit(EXIT_SUCCESS);
}

Resultado:

Hello There! thread 0, pthread ID - 140215498864384
Hello There! thread 1, pthread ID - 140215490471680
Hello There! thread 3, pthread ID - 140215473686272
Hello There! thread 2, pthread ID - 140215482078976

Use a função thrd_join para esperar pelo thread fornecido em C

thrd_join é um análogo da função pthread_join, e bloqueia o thread atual até que o thread fornecido termine a execução. Leva dois argumentos: identificador de thread e ponteiro int denotando o local onde o código de status de retorno pode ser armazenado opcionalmente se o usuário fornecer o endereço válido. Se o thrd_join for chamado em um thread que já foi separado ou unido, o resultado é um comportamento indefinido. A função retorna os valores correspondentes a thrd_success ou thrd_error.

O próximo exemplo de código implementa o cenário em que quatro threads incrementam a variável de tipo atomic_int. Finalmente, o thread principal que espera que outros terminem imprime o valor de soma final de counter.

#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>

#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif

atomic_int counter = 0;

enum { MAX_ITER = 1000 };

void *printHello(void *thr_id) {
  long tid;
  tid = (long)thr_id;
  printf("thread %ld started incrementing ID - %lu\n", tid, thrd_current());

  for (int i = 0; i < MAX_ITER; ++i) {
    counter += 1;
  }

  return NULL;
}

int main(int argc, char const *argv[]) {
  thrd_t threads[NUM_THREADS];
  int rc;
  long t;

  for (t = 0; t < NUM_THREADS; t++) {
    rc = thrd_create(&threads[t], (thrd_start_t)printHello, (void *)t);
    if (rc == thrd_error) {
      printf("ERORR; thrd_create() call failed\n");
      exit(EXIT_FAILURE);
    }
  }

  for (t = 0; t < NUM_THREADS; t++) {
    thrd_join(threads[t], NULL);
  }
  printf("count = %d\n", counter);

  thrd_exit(EXIT_SUCCESS);
}

Resultado:

thread 0 started incrementing ID - 139729818216192
thread 2 started incrementing ID - 139729801430784
thread 3 started incrementing ID - 139729793038080
thread 1 started incrementing ID - 139729809823488
count = 4000
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C Thread