How to Use the C11 Threads Library in C

Jinku Hu Feb 02, 2024
  1. Use the thrd_create Function to Create a New Thread and Execute the Given Routine in C
  2. Use the thrd_join Function to Wait for the Given Thread in C
How to Use the C11 Threads Library in C

This article will explain several methods of how to use the C11 threads library in C.

Use the thrd_create Function to Create a New Thread and Execute the Given Routine in C

Threading support has been long overdue in the standard C language specification, and it was finally realized in C11. Before that, the POSIX threads API was used as the primary tool to utilize multi-threaded programming. Since the C11 provided a more standard interface that could be used without platform dependencies, it has been recommended to use the ISO language API than the POSIX version. Although the two APIs don’t match in their function prototypes, the main features are mostly similar. In the following example, we demonstrate the simple scenario where four threads are started to execute the printHello function and then terminate without joining the main thread.

thrd_create takes three arguments,

  1. The first is a pointer to the thread identifier.
  2. The second argument is of type - thrd_start_t, which is just typedef for a function pointer prototype.
  3. The third parameter specifies an argument that can be passed to the function.

The return status codes of thrd_create are defined using the enum values: thrd_success, thrd_nomem and 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);
}

Output:

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 the thrd_join Function to Wait for the Given Thread in C

thrd_join is an analog of the pthread_join function, and it blocks the current thread until the given thread finishes the execution. It takes two arguments: thread identifier and int pointer denoting the location where return status code can be stored optionally if the user supplies the valid address. If the thrd_join is called on a thread that was already detached or joined, the result is undefined behavior. The function returns the values corresponding to thrd_success or thrd_error.

The next example code implements the scenario where four threads increment the atomic_int type variable. Finally, the main thread that waits for others to finish prints the final sum value of 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);
}

Output:

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
Author: 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

Related Article - C Thread