GNU C语言的"__thread"与C11关键字_Thread_local等效,这里只说一下C11的。
#define thread_local _Thread_local //(since C11, then removed in C23)
Since C23, thread_local is itself a keyword, which may also be a predefined macro, so <threads.h> no longer provides it.
需要说明的是,c11引入的_Thread_local关键字在c23标准中可以直接使用thread_local ,也即c23标准_Thread_local关键字被废弃了。
有且只有 thread_local 关键字修饰的变量具有线程(thread)周期,这些变量在线程开始的时候被生成,在线程结束的时候被销毁,并且每一个线程都拥有一个独立的变量实例。
thread_local 一般用于需要保证线程安全的函数中。
以下部分在一些编译器中还没有实现。
在标准的 C 语言规范中,对线程的支持迟迟没有出现,终于在 C11 中实现了。在此之前,POSIX 线程 API 被用作利用多线程编程的主要工具。由于 C11 提供了更标准的接口,可以在不依赖平台的情况下使用,因此建议使用 ISO 语言 API,而不要使用 POSIX 版本。尽管这两个 API 的功能原型不匹配,但主要功能大多相似。在下面的示例中,我们演示了一个简单的场景,其中启动了四个线程来执行 printHello
函数,然后在不加入主线程的情况下终止该线程。
thrd_create
接受三个参数,
- 第一个是指向线程标识符的指针。
- 第二个参数的类型为
thrd_start_t
,对于函数指针原型而言,其名称仅为typedef
。 - 第三个参数指定可以传递给函数的参数。
使用枚举值定义 thrd_create
的返回状态代码:thrd_success
,thrd_nomem
和 thrd_error
。
thrd_join
是 pthread_join
函数的一个类比,它将阻塞当前线程,直到给定线程完成执行。它带有两个参数:线程标识符和 int
指针,表示如果用户提供有效地址,则可以选择存储返回状态代码的位置。如果在已经分离或联接的线程上调用 thrd_join
,则结果是未定义的行为。该函数返回对应于 thrd_success
或 thrd_error
的值。
下一个示例代码实现了四个线程递增 atomic_int
类型变量的情况。最后,等待其他线程完成的主线程将打印 counter
的最终总和值。
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <unistd.h>#ifndef NUM_THREADS
#define NUM_THREADS 4
#endifatomic_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);
}
输出
参考资料:
1. thread_local
2. C11 GCC threads.h not found