# threads.h POSIX pthreads work great on Linux but are not available everywhere. **`threads.h`** (C11) provides a portable threading API — thread creation, mutexes, condition variables, and thread-local storage — with a standardised interface that any conforming C11 implementation must provide. The API surface: | Function | Purpose | | `thrd_create(t, fn, arg)` | Create a thread running `fn(arg)` | | `thrd_join(t, res)` | Wait for thread, optionally get return value | | `thrd_exit(code)` | Exit current thread with a code | | `mtx_init`, `mtx_lock`, `mtx_unlock`, `mtx_destroy` | Mutex lifecycle | | `cnd_init`, `cnd_wait`, `cnd_signal`, `cnd_broadcast`, `cnd_destroy` | Condition variables | | `tss_create`, `tss_get`, `tss_set`, `tss_delete` | Thread-specific storage | Mutex types: `mtx_plain` (non-recursive), `mtx_recursive` (same thread can lock multiple times), `mtx_timed` (adds `mtx_timedlock`). In practice, Linux programs tend to use pthreads directly or C++ ``, since `` support was absent from glibc until 2022 (version 2.36). For new portable C11 code it is the right choice; for existing Linux-only code, pthreads is more common. ## Practice ```c // compile: gcc -o thrdemo thrdemo.c -lpthread // run: ./thrdemo // description: two threads increment a shared counter under a mutex #include #include mtx_t lock; int counter = 0; int worker(void *arg) { (void)arg; for (int i = 0; i < 100000; i++) { mtx_lock(&lock); counter++; mtx_unlock(&lock); } return 0; } int main(void) { mtx_init(&lock, mtx_plain); thrd_t t1, t2; thrd_create(&t1, worker, NULL); thrd_create(&t2, worker, NULL); thrd_join(t1, NULL); thrd_join(t2, NULL); printf("counter: %d\n", counter); // 200000 mtx_destroy(&lock); return 0; } ``` Remove the `mtx_lock`/`mtx_unlock` calls and run again — the counter will almost certainly land below 200000 due to the data race. This is the canonical demonstration of why shared mutable state needs synchronisation even for a single increment.