Linux多线程编程实例代码分析

来源:网络学院作者:阿亮头衔:草根站长
导读:本期聚焦于小伙伴创作的《Linux多线程编程实例代码分析》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Linux多线程编程实例代码分析》有用,将其分享出去将是对创作者最好的鼓励。

Linux多线程编程是服务端开发、高性能计算场景中常用的技术,通过pthread库可以在Linux系统中创建和管理多个线程,实现任务的并发执行,提升程序的运行效率。合理的多线程设计能够充分利用多核CPU资源,同时需要注意线程间的同步与通信,避免出现数据竞争、死锁等问题。

Linux多线程编程实例代码分析

线程创建基础实例

使用pthread库创建线程需要包含<pthread.h>头文件,编译时需要链接pthread库,添加-lpthread参数。下面是一个最简单的线程创建示例,主线程创建一个子线程,子线程执行自定义的任务函数。

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

// 子线程执行的任务函数
void* thread_task(void* arg) {
    // 将传入的参数转换为int类型
    int thread_id = *(int*)arg;
    printf("子线程 %d 开始执行n", thread_id);
    sleep(2); // 模拟任务执行耗时
    printf("子线程 %d 执行结束n", thread_id);
    return NULL;
}

int main() {
    pthread_t tid; // 线程ID变量
    int thread_arg = 1; // 传递给子线程的参数
    
    // 创建线程,第一个参数是线程ID指针,第二个是线程属性,第三个是任务函数,第四个是参数
    int ret = pthread_create(&tid, NULL, thread_task, &thread_arg);
    if (ret != 0) {
        printf("线程创建失败,错误码:%dn", ret);
        return -1;
    }
    
    printf("主线程等待子线程执行完成n");
    // 等待子线程结束,回收资源
    pthread_join(tid, NULL);
    printf("主线程执行结束n");
    
    return 0;
}

上述代码中,pthread_create函数用于创建线程,第一个参数&tid用来存储新创建线程的ID,第二个参数为线程属性,传入NULL表示使用默认属性,第三个参数是线程启动后执行的函数指针,第四个参数是传递给任务函数的参数。主线程调用pthread_join等待子线程执行完成,避免主线程提前退出导致子线程未执行完毕。

线程间参数传递与返回值

线程任务函数可以接收参数并返回结果,参数和返回值都是void*类型,需要根据实际类型进行转换。下面的示例演示了如何传递结构体参数,并获取子线程的返回结果。

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

// 定义传递给线程的参数结构体
typedef struct {
    int task_id;
    char task_name[32];
} ThreadArg;

// 定义线程返回结果结构体
typedef struct {
    int status;
    char result_msg[64];
} ThreadResult;

void* thread_work(void* arg) {
    ThreadArg* t_arg = (ThreadArg*)arg;
    printf("接收到任务:id=%d, name=%sn", t_arg->task_id, t_arg->task_name);
    
    // 分配返回结果内存,注意需要动态分配,否则线程结束后内存会被释放
    ThreadResult* res = (ThreadResult*)malloc(sizeof(ThreadResult));
    res->status = 0;
    strcpy(res->result_msg, "任务执行成功");
    
    // 释放参数内存,参数如果是动态分配的需要在合适的时机释放
    free(t_arg);
    return (void*)res;
}

int main() {
    pthread_t tid;
    // 动态分配参数内存
    ThreadArg* arg = (ThreadArg*)malloc(sizeof(ThreadArg));
    arg->task_id = 1001;
    strcpy(arg->task_name, "数据处理任务");
    
    int ret = pthread_create(&tid, NULL, thread_work, arg);
    if (ret != 0) {
        printf("线程创建失败n");
        free(arg);
        return -1;
    }
    
    ThreadResult* thread_res = NULL;
    // 获取线程返回结果
    pthread_join(tid, (void**)&thread_res);
    if (thread_res != NULL) {
        printf("线程返回结果:status=%d, msg=%sn", thread_res->status, thread_res->result_msg);
        free(thread_res);
    }
    
    return 0;
}

需要注意的是,传递给线程的参数如果是局部变量,可能会出现主线程修改参数值或者局部变量销毁的情况,因此建议动态分配参数内存,在子线程中使用完成后释放。线程的返回结果也需要动态分配内存,主线程通过pthread_join获取结果后再释放,避免内存泄漏。

线程同步:互斥锁的使用

当多个线程同时操作共享资源时,会出现数据竞争问题,需要使用互斥锁保证同一时间只有一个线程可以访问共享资源。下面的示例演示了互斥锁的基本使用场景。

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

int shared_count = 0; // 共享资源
pthread_mutex_t count_mutex; // 互斥锁变量

void* increment_count(void* arg) {
    int thread_id = *(int*)arg;
    for (int i = 0; i < 10000; i++) {
        // 加锁,获取互斥锁
        pthread_mutex_lock(&count_mutex);
        shared_count++; // 操作共享资源
        // 解锁,释放互斥锁
        pthread_mutex_unlock(&count_mutex);
    }
    printf("线程 %d 执行完成n", thread_id);
    return NULL;
}

int main() {
    pthread_t tids[4];
    int thread_ids[4] = {1,2,3,4};
    
    // 初始化互斥锁
    pthread_mutex_init(&count_mutex, NULL);
    
    // 创建4个线程同时操作共享变量
    for (int i = 0; i < 4; i++) {
        pthread_create(&tids[i], NULL, increment_count, &thread_ids[i]);
    }
    
    // 等待所有线程执行完成
    for (int i = 0; i < 4; i++) {
        pthread_join(tids[i], NULL);
    }
    
    // 销毁互斥锁
    pthread_mutex_destroy(&count_mutex);
    
    printf("最终共享计数结果:%dn", shared_count);
    return 0;
}

代码中首先通过pthread_mutex_init初始化互斥锁,线程在操作共享变量shared_count前调用pthread_mutex_lock加锁,操作完成后调用pthread_mutex_unlock解锁,保证同一时间只有一个线程可以修改shared_count。最后使用pthread_mutex_destroy销毁互斥锁,释放相关资源。如果不使用互斥锁,4个线程各累加10000次,最终的结果大概率会小于40000,因为存在多个线程同时修改共享变量的问题。

线程同步:条件变量的使用

条件变量通常和互斥锁配合使用,用于线程间的等待和通知机制,比如一个线程需要等待某个条件满足后再继续执行。下面的示例模拟生产者消费者场景,生产者线程生产数据后通知消费者线程消费。

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

// 共享队列,最多存放5个数据
int queue[5];
int queue_size = 0;
int queue_front = 0;
int queue_rear = 0;

pthread_mutex_t queue_mutex;
pthread_cond_t queue_not_full; // 队列不满条件变量
pthread_cond_t queue_not_empty; // 队列不空条件变量

// 生产者线程函数
void* producer(void* arg) {
    int data = 0;
    while (1) {
        pthread_mutex_lock(&queue_mutex);
        // 等待队列不满的条件
        while (queue_size >= 5) {
            printf("队列已满,生产者等待n");
            pthread_cond_wait(&queue_not_full, &queue_mutex);
        }
        // 生产数据放入队列
        queue[queue_rear] = data;
        queue_rear = (queue_rear + 1) % 5;
        queue_size++;
        printf("生产者生产数据:%d,当前队列大小:%dn", data, queue_size);
        data++;
        // 通知消费者队列不空
        pthread_cond_signal(&queue_not_empty);
        pthread_mutex_unlock(&queue_mutex);
        sleep(1); // 模拟生产耗时
    }
    return NULL;
}

// 消费者线程函数
void* consumer(void* arg) {
    while (1) {
        pthread_mutex_lock(&queue_mutex);
        // 等待队列不空的条件
        while (queue_size <= 0) {
            printf("队列已空,消费者等待n");
            pthread_cond_wait(&queue_not_empty, &queue_mutex);
        }
        // 从队列取出数据
        int data = queue[queue_front];
        queue_front = (queue_front + 1) % 5;
        queue_size--;
        printf("消费者消费数据:%d,当前队列大小:%dn", data, queue_size);
        // 通知生产者队列不满
        pthread_cond_signal(&queue_not_full);
        pthread_mutex_unlock(&queue_mutex);
        sleep(2); // 模拟消费耗时
    }
    return NULL;
}

int main() {
    pthread_t prod_tid, cons_tid;
    
    // 初始化互斥锁和条件变量
    pthread_mutex_init(&queue_mutex, NULL);
    pthread_cond_init(&queue_not_full, NULL);
    pthread_cond_init(&queue_not_empty, NULL);
    
    // 创建生产者和消费者线程
    pthread_create(&prod_tid, NULL, producer, NULL);
    pthread_create(&cons_tid, NULL, consumer, NULL);
    
    // 等待线程(这里实际不会结束,仅作示例)
    pthread_join(prod_tid, NULL);
    pthread_join(cons_tid, NULL);
    
    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&queue_mutex);
    pthread_cond_destroy(&queue_not_full);
    pthread_cond_destroy(&queue_not_empty);
    
    return 0;
}

条件变量的pthread_cond_wait函数会先释放互斥锁,然后阻塞等待条件满足,当其他线程调用pthread_cond_signal或者pthread_cond_broadcast通知时,该函数会重新获取互斥锁再返回。这里使用while循环判断条件而不是if,是为了避免虚假唤醒问题,确保条件真正满足后再继续执行后续逻辑。

常见问题与注意事项

  • 编译pthread相关代码时,必须添加-lpthread链接选项,否则会出现函数未定义的编译错误。
  • 线程任务函数的参数和返回值都是void*类型,转换时需要注意类型匹配,避免内存访问错误。
  • 互斥锁必须成对使用,加锁后一定要解锁,否则会导致死锁,同时不要重复解锁同一个互斥锁。
  • 线程结束后如果不调用pthread_join回收,会产生僵尸线程,浪费系统资源;如果不想阻塞主线程,可以设置线程为分离状态,使用pthread_detach函数。
  • 条件变量必须和互斥锁配合使用,等待条件时先获取互斥锁,再调用等待函数,避免错过通知信号。

Linux多线程编程pthread线程同步线程创建修改时间:2026-07-09 16:24:48

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。