Skip to content

线程

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 时间片

注意事项

  1. 检查编译器支持,注意是否需要特殊编译选项
  2. 检查返回值,进行错误处理
  3. 注意资源的正确释放
  4. 避免死锁