POSIX线程编程实战指南

POSIX线程编程核心指南

目录

✅ 一、什么是 POSIX 线程(pthreads)?

✅ 二、核心数据类型与函数

✅ 三、线程创建与等待:pthread_create 和 pthread_join

🔧 函数原型

✅ 示例:创建并等待线程

输出:

✅ 四、线程属性(pthread_attr_t)

示例:设置线程栈大小

✅ 五、线程分离:pthread_detach

✅ 六、线程同步:互斥锁(Mutex)

🔧 基本操作

✅ 示例:线程安全计数器

✅ 七、条件变量(Condition Variables)

🔧 常用函数

✅ 示例:生产者-消费者模型

✅ 八、线程局部存储(Thread-Local Storage)

方式1:__thread(GCC 扩展)

方式2:pthread_key_t(可移植)

✅ 九、线程取消与清理

取消线程

清理处理程序

✅ 十、常见错误与最佳实践

✅ 十一、调试工具

✅ 总结:pthreads 核心要点


以下是 POSIX 线程(pthreads)全面、系统、实战导向 的详解,适合从入门到掌握多线程编程。


✅ 一、什么是 POSIX 线程(pthreads)?

  • POSIX:Portable Operating System Interface,一套 Unix/Linux 系统的标准。
  • pthreads:POSIX Threads,定义了创建和操作线程的 API。
  • 平台支持:Linux、macOS、FreeBSD 等类 Unix 系统原生支持。
  • 头文件#include <pthread.h>
  • 链接库:编译时需加 -lpthread
gcc program.c -o program -lpthread

✅ 二、核心数据类型与函数

类型/函数说明
pthread_t线程 ID 类型
pthread_create()创建线程
pthread_join()等待线程结束
pthread_detach()分离线程(自动回收资源)
pthread_exit()线程主动退出
pthread_cancel()取消线程
pthread_mutex_t互斥锁类型
pthread_cond_t条件变量类型

✅ 三、线程创建与等待:pthread_create 和 pthread_join

🔧 函数原型

int pthread_create(
    pthread_t *thread,           // 输出:线程 ID
    const pthread_attr_t *attr,  // 属性(NULL 表示默认)
    void *(*start_routine)(void *), // 线程函数
    void *arg                    // 传给线程函数的参数
);

成功返回 0,失败返回错误码(非 errno)。


✅ 示例:创建并等待线程

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_func(void *arg)
{
    int id = *(int *)arg;
    printf("Thread %d is running...\n", id);
    sleep(2);
    printf("Thread %d exiting.\n", id);
    return (void *)(long)(id * 100); // 返回值
}

int main()
{
    pthread_t tid;
    int thread_id = 1;

    // 创建线程
    if (pthread_create(&tid, NULL, thread_func, &thread_id) != 0)
    {
        perror("pthread_create failed");
        return 1;
    }

    // 等待线程结束,并获取返回值
    void *result;
    pthread_join(tid, &result);

    printf("Thread returned: %ld\n", (long)result);
    printf("Main thread exiting.\n");
    return 0;
}

输出:

Thread 1 is running...
Thread 1 exiting.
Thread returned: 100
Main thread exiting.

✅ 四、线程属性(pthread_attr_t)

用于设置线程的栈大小、分离状态、调度策略等。

示例:设置线程栈大小

pthread_attr_t attr;
pthread_t tid;

pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 1024); // 1MB 栈

pthread_create(&tid, &attr, thread_func, NULL);

pthread_attr_destroy(&attr); // 释放属性对象

✅ 五、线程分离:pthread_detach

  • pthread_join:主线程等待,资源由主线程回收。
  • pthread_detach:线程结束后自动释放资源,不能 join
// 方式1:创建后分离
pthread_detach(tid);

// 方式2:线程内部自分离
void *thread_func(void *arg)
{
    pthread_detach(pthread_self());
    // ... 工作
    pthread_exit(NULL);
}

✅ 六、线程同步:互斥锁(Mutex)

防止多个线程同时访问共享数据。

🔧 基本操作

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 静态初始化

// 或动态初始化
// pthread_mutex_init(&mutex, NULL);

pthread_mutex_lock(&mutex);   // 加锁
// 访问共享资源
pthread_mutex_unlock(&mutex); // 解锁

// 销毁
// pthread_mutex_destroy(&mutex);

✅ 示例:线程安全计数器

#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 10
#define LOOP_COUNT 100000

long long counter = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *increment(void *arg)
{
    for (int i = 0; i < LOOP_COUNT; i++)
    {
        pthread_mutex_lock(&mutex);
        counter++;
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main()
{
    pthread_t threads[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++)
    {
        pthread_create(&threads[i], NULL, increment, NULL);
    }

    for (int i = 0; i < NUM_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }

    printf("Expected: %d, Actual: %lld\n", NUM_THREADS * LOOP_COUNT, counter);
    return 0;
}

✅ 七、条件变量(Condition Variables)

用于线程间通信,实现“等待-通知”机制。

🔧 常用函数

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

pthread_cond_wait(&cond, &mutex);        // 等待条件
pthread_cond_signal(&cond);              // 唤醒一个等待线程
pthread_cond_broadcast(&cond);           // 唤醒所有等待线程

✅ 示例:生产者-消费者模型

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int count = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;

void *producer(void *arg)
{
    for (int i = 0; i < 20; i++)
    {
        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE)
        {
            printf("Buffer full, producer waiting...\n");
            pthread_cond_wait(&not_full, &mutex);
        }

        buffer[count++] = i;
        printf("Produced: %d, count = %d\n", i, count);

        pthread_cond_signal(&not_empty);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    return NULL;
}

void *consumer(void *arg)
{
    for (int i = 0; i < 20; i++)
    {
        pthread_mutex_lock(&mutex);
        while (count == 0)
        {
            printf("Buffer empty, consumer waiting...\n");
            pthread_cond_wait(&not_empty, &mutex);
        }

        int item = buffer[--count];
        printf("Consumed: %d, count = %d\n", item, count);

        pthread_cond_signal(&not_full);
        pthread_mutex_unlock(&mutex);
        sleep(2);
    }
    return NULL;
}

int main()
{
    pthread_t prod, cons;
    pthread_create(&prod, NULL, producer, NULL);
    pthread_create(&cons, NULL, consumer, NULL);

    pthread_join(prod, NULL);
    pthread_join(cons, NULL);
    return 0;
}

✅ 八、线程局部存储(Thread-Local Storage)

每个线程拥有独立的变量副本。

方式1:__thread(GCC 扩展)

__thread int thread_local_var = 0;

void *thread_func(void *arg)
{
    thread_local_var = arg;
    printf("Thread %d has value %d\n", (int)(long)arg, thread_local_var);
    return NULL;
}

方式2:pthread_key_t(可移植)

pthread_key_t key;

void destructor(void *value)
{
    free(value);
}

// 初始化
pthread_key_create(&key, destructor);

// 设置
int *val = malloc(sizeof(int));
*val = 100;
pthread_setspecific(key, val);

// 获取
int *my_val = pthread_getspecific(key);

✅ 九、线程取消与清理

取消线程

pthread_cancel(tid); // 请求取消线程

线程需设置取消状态和类型:

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

清理处理程序

void cleanup_handler(void *arg)
{
    printf("Cleaning up: %s\n", (char *)arg);
}

void *thread_func(void *arg)
{
    pthread_cleanup_push(cleanup_handler, "resource 1");
    pthread_cleanup_push(cleanup_handler, "resource 2");

    // 工作...

    pthread_cleanup_pop(0); // 0: 不执行,1: 执行
    pthread_cleanup_pop(0);
    return NULL;
}

✅ 十、常见错误与最佳实践

问题解决方案
数据竞争使用 mutex 保护共享数据
死锁避免嵌套锁,按固定顺序加锁
资源泄漏使用 pthread_join 或 pthread_detach
线程不安全函数使用可重入版本(如 strtok_r
性能瓶颈减少锁粒度,使用读写锁

✅ 十一、调试工具

  • valgrind --tool=helgrind:检测数据竞争、死锁
  • gdb:调试多线程程序(info threadsthread N

✅ 总结:pthreads 核心要点

操作函数
创建线程pthread_create
等待线程pthread_join
分离线程pthread_detach
互斥锁pthread_mutex_lock/unlock
条件变量pthread_cond_wait/signal
线程局部存储pthread_key_create / __thread
取消线程pthread_cancel + 清理函数

建议

  • 优先使用 pthreads 进行 Linux/macOS 多线程开发。
  • 避免全局变量,使用参数传递数据。
  • 尽量使用 pthread_join 回收资源,避免分离线程滥用。

需要我提供一个 线程池(Thread Pool) 的完整实现示例吗?这是高性能服务器的常见模式。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值