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 -
Use the
thrd_join
Function to Wait for the Given Thread 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,
- The first is a pointer to the thread identifier.
- The second argument is of type -
thrd_start_t
, which is justtypedef
for a function pointer prototype. - 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
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