线程
C11 标准引入了线程支持库(<threads.h>
),提供了标准的多线程编程接口。
threads.h
线程类型和函数
主要类型:
thrd_t
: 线程标识符mtx_t
: 互斥锁cnd_t
: 条件变量tss_t
: 线程局部存储once_flag
: 一次性初始化标记
主要函数:
thrd_create()
: 创建线程thrd_join()
: 等待线程结束mtx_init()
: 初始化互斥锁mtx_lock()
: 锁定互斥锁mtx_unlock()
: 解锁互斥锁cnd_signal()
: 发送信号cnd_wait()
: 等待条件变量tss_set()
: 设置线程局部存储tss_get()
: 获取线程局部存储tss_delete()
: 删除线程局部存储
创建线程
使用 thrd_create
函数创建新线程:
c
#include <threads.h>
#include <stdio.h>
int thread_func(void* arg) {
printf("线程运行中...\n");
return 0;
}
int main(void) {
thrd_t thr;
int result = thrd_create(&thr, thread_func, NULL);
if (result != thrd_success) {
printf("创建线程失败\n");
return 1;
}
// 等待线程结束
thrd_join(thr, NULL);
return 0;
}
互斥锁
保护共享资源:
c
#include <threads.h>
mtx_t mutex;
int shared_data = 0;
int main(void) {
// 初始化互斥锁
if (mtx_init(&mutex, mtx_plain) != thrd_success) {
return 1;
}
// 使用互斥锁
mtx_lock(&mutex);
shared_data++; // 临界区
mtx_unlock(&mutex);
// 销毁互斥锁
mtx_destroy(&mutex);
return 0;
}
条件变量
用于线程同步:
c
#include <threads.h>
mtx_t mutex;
cnd_t cond;
int ready = 0;
int producer(void* arg) {
mtx_lock(&mutex);
ready = 1;
cnd_signal(&cond);
mtx_unlock(&mutex);
return 0;
}
int consumer(void* arg) {
mtx_lock(&mutex);
while (!ready) {
cnd_wait(&cond, &mutex);
}
mtx_unlock(&mutex);
return 0;
}
线程局部存储
每个线程独有的存储空间:
c
#include <threads.h>
tss_t key;
void destructor(void* data) {
free(data);
}
int thread_func(void* arg) {
int* value = malloc(sizeof(int));
*value = 42;
// 设置线程局部存储
tss_set(key, value);
// 获取线程局部存储
int* stored = tss_get(key);
printf("值: %d\n", *stored);
return 0;
}
int main(void) {
// 创建线程局部存储键
if (tss_create(&key, destructor) != thrd_success) {
return 1;
}
// ... 创建线程等操作 ...
tss_delete(key);
return 0;
}
一次性初始化
确保初始化代码只执行一次:
c
#include <threads.h>
once_flag flag = ONCE_FLAG_INIT;
void init_function(void) {
// 只执行一次的初始化代码
printf("初始化...\n");
}
int thread_func(void* arg) {
call_once(&flag, init_function);
return 0;
}
返回值和错误处理
线程函数的返回值:
thrd_success
: 成功thrd_error
: 一般错误thrd_nomem
: 内存不足thrd_timedout
: 超时thrd_busy
: 资源忙
其他重要函数
thrd_current()
: 获取当前线程标识符thrd_equal()
: 比较两个线程标识符thrd_sleep()
: 线程休眠thrd_yield()
: 让出 CPU 时间片
注意事项
- 检查编译器支持,注意是否需要特殊编译选项
- 检查返回值,进行错误处理
- 注意资源的正确释放
- 避免死锁