C语言多线程编程完全指南

多线程编程是现代程序提高并发性能的重要手段。C语言通过pthread库提供强大的多线程支持,本文详细介绍线程创建、同步机制与线程池的实现。

线程基础概念

线程是程序执行的最小单位,同一进程内的线程共享进程的地址空间、全局变量和打开的文件描述符。与进程相比,线程创建和切换的开销更小。

线程创建与结束

使用pthread_create创建新线程,pthread_join等待线程结束:

#include 
#include 
#include 

void* thread_worker(void *arg) {
    int *num = (int*)arg;
    printf("Thread running with arg: %d\n", *num);
    return NULL;
}

int main(void) {
    pthread_t tid;
    int param = 42;

    /* 创建新线程 */
    if (pthread_create(&tid, NULL, thread_worker, ¶m) != 0) {
        perror("pthread_create");
        return 1;
    }

    /* 等待线程结束 */
    pthread_join(tid, NULL);
    printf("Thread finished\n");
    return 0;
}

互斥锁

互斥锁用于保护共享资源,防止多个线程同时访问造成数据竞争:

typedef struct {
    int counter;
    pthread_mutex_t mutex;
} Counter;

void counter_inc(Counter *c) {
    pthread_mutex_lock(&c->mutex);  /* 加锁 */
    c->counter++;
    pthread_mutex_unlock(&c->mutex);  /* 解锁 */
}

/* 初始化互斥锁 */
Counter c = {0, PTHREAD_MUTEX_INITIALIZER};

条件变量

条件变量用于线程间的同步,允许线程等待某个条件成立:

typedef struct {
    int ready;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} Context;

/* 等待条件 */
void wait_ready(Context *ctx) {
    pthread_mutex_lock(&ctx->mutex);
    while (!ctx->ready) {
        pthread_cond_wait(&ctx->cond, &ctx->mutex);
    }
    pthread_mutex_unlock(&ctx->mutex);
}

/* 发送信号 */
void signal_ready(Context *ctx) {
    pthread_mutex_lock(&ctx->mutex);
    ctx->ready = 1;
    pthread_cond_signal(&ctx->cond);
    pthread_mutex_unlock(&ctx->mutex);
}

读写锁

读写锁适合读多写少的场景,允许多个线程同时读,但写操作需要独占:

typedef struct {
    int data;
    pthread_rwlock_t rwlock;
} SharedData;

/* 读操作 */
int read_data(SharedData *sd) {
    int val;
    pthread_rwlock_rdlock(&sd->rwlock);
    val = sd->data;
    pthread_rwlock_unlock(&sd->rwlock);
    return val;
}

/* 写操作 */
void write_data(SharedData *sd, int val) {
    pthread_rwlock_wrlock(&sd->rwlock);
    sd->data = val;
    pthread_rwlock_unlock(&sd->rwlock);
}

线程池实现

线程池预先创建一组工作线程,避免频繁创建销毁线程的开销:

typedef struct {
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    pthread_t *workers;
    void *(*task_fn)(void*);
    void *task_arg;
    int shutdown;
    int count;
} ThreadPool;

void* worker_loop(void *arg) {
    ThreadPool *pool = (ThreadPool*)arg;
    while(1) {
        pthread_mutex_lock(&pool->mutex);
        while (pool->task_fn == NULL && !pool->shutdown) {
            pthread_cond_wait(&pool->cond, &pool->mutex);
        }
        if (pool->shutdown) break;

        void *(*fn)(void*) = pool->task_fn;
        void *arg = pool->task_arg;
        pool->task_fn = NULL;
        pthread_mutex_unlock(&pool->mutex);

        fn(arg);
    }
    pthread_mutex_unlock(&pool->mutex);
    return NULL;
}

注意事项

多线程编程需要注意:避免死锁(按相同顺序加锁)、减少锁粒度、使用线程安全函数。

总结

  • pthread库提供完整的线程支持
  • 互斥锁用于保护共享资源
  • 条件变量实现线程同步
  • 读写锁适合读多写少场景
  • 线程池提高频繁任务的执行效率