插件窝 干货文章 Linux多线程编程实例代码分析

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

pthread 线程 mutex TASK 778    来源:    2025-04-21

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

基本多线程示例

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

#define NUM_THREADS 5

// 线程函数
void *print_hello(void *threadid) {
    long tid = (long)threadid;
    printf("Hello World! It's me, thread #%ld!\n", tid);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    for(t = 0; t < NUM_THREADS; t++) {
        printf("In main: creating thread %ld\n", t);
        rc = pthread_create(&threads[t], NULL, print_hello, (void *)t);

        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    // 等待所有线程完成
    for(t = 0; t < NUM_THREADS; t++) {
        pthread_join(threads[t], NULL);
    }

    printf("All threads completed.\n");
    pthread_exit(NULL);
}

代码分析:

  1. 包含必要的头文件:pthread.h用于线程操作
  2. 定义线程数量NUM_THREADS为5
  3. print_hello是线程函数,接收一个void指针参数
  4. pthread_create创建新线程
  5. pthread_join等待线程结束
  6. 主线程最后调用pthread_exit退出

使用互斥锁的线程同步示例

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

#define NUM_THREADS 5
int counter = 0;
pthread_mutex_t mutex;

void *increment_counter(void *threadid) {
    long tid = (long)threadid;

    pthread_mutex_lock(&mutex);
    printf("Thread #%ld working on counter\n", tid);
    int temp = counter;
    temp++;
    counter = temp;
    printf("Thread #%ld: counter = %d\n", tid, counter);
    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

    for(t = 0; t < NUM_THREADS; t++) {
        rc = pthread_create(&threads[t], NULL, increment_counter, (void *)t);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

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

    printf("Final counter value: %d\n", counter);
    pthread_mutex_destroy(&mutex);
    pthread_exit(NULL);
}

代码分析:

  1. 定义全局变量counter和互斥锁mutex
  2. pthread_mutex_init初始化互斥锁
  3. 线程函数中使用pthread_mutex_lockpthread_mutex_unlock保护临界区
  4. 最后用pthread_mutex_destroy销毁互斥锁

使用条件变量的生产者-消费者模型

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

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_producer = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER;

void *producer(void *arg) {
    int item;
    for(int i = 0; i < 10; i++) {
        item = rand() % 100; // 生产一个随机数

        pthread_mutex_lock(&mutex);
        while(count == BUFFER_SIZE) {
            pthread_cond_wait(&cond_producer, &mutex);
        }

        buffer[in] = item;
        in = (in + 1) % BUFFER_SIZE;
        count++;
        printf("Produced: %d, count: %d\n", item, count);

        pthread_cond_signal(&cond_consumer);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

void *consumer(void *arg) {
    int item;
    for(int i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while(count == 0) {
            pthread_cond_wait(&cond_consumer, &mutex);
        }

        item = buffer[out];
        out = (out + 1) % BUFFER_SIZE;
        count--;
        printf("Consumed: %d, count: %d\n", item, count);

        pthread_cond_signal(&cond_producer);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

int main() {
    pthread_t producer_thread, consumer_thread;

    pthread_create(&producer_thread, NULL, producer, NULL);
    pthread_create(&consumer_thread, NULL, consumer, NULL);

    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_producer);
    pthread_cond_destroy(&cond_consumer);

    return 0;
}

代码分析:

  1. 使用循环缓冲区实现生产者-消费者模型
  2. 定义互斥锁和两个条件变量
  3. 生产者线程在缓冲区满时等待,消费者线程在缓冲区空时等待
  4. 使用pthread_cond_wait等待条件变量,pthread_cond_signal通知等待的线程
  5. 最后销毁互斥锁和条件变量

线程池实现示例

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

#define THREAD_POOL_SIZE 4
#define TASK_QUEUE_SIZE 10

typedef struct {
    void (*function)(void *);
    void *arg;
} Task;

Task task_queue[TASK_QUEUE_SIZE];
int task_count = 0;
int queue_front = 0, queue_rear = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_t thread_pool[THREAD_POOL_SIZE];

void execute_task(Task *task) {
    task->function(task->arg);
}

void *thread_function(void *arg) {
    while(1) {
        pthread_mutex_lock(&mutex);
        while(task_count == 0) {
            pthread_cond_wait(&cond, &mutex);
        }

        Task task = task_queue[queue_front];
        queue_front = (queue_front + 1) % TASK_QUEUE_SIZE;
        task_count--;

        pthread_mutex_unlock(&mutex);
        execute_task(&task);
    }
    return NULL;
}

void submit_task(void (*function)(void *), void *arg) {
    pthread_mutex_lock(&mutex);

    if(task_count == TASK_QUEUE_SIZE) {
        printf("Task queue is full!\n");
        pthread_mutex_unlock(&mutex);
        return;
    }

    Task task;
    task.function = function;
    task.arg = arg;

    task_queue[queue_rear] = task;
    queue_rear = (queue_rear + 1) % TASK_QUEUE_SIZE;
    task_count++;

    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
}

void sample_task(void *arg) {
    int num = *(int *)arg;
    printf("Task %d is being processed by thread %lu\n", num, pthread_self());
    sleep(1); // 模拟耗时操作
    printf("Task %d completed\n", num);
}

int main() {
    // 初始化线程池
    for(int i = 0; i < THREAD_POOL_SIZE; i++) {
        pthread_create(&thread_pool[i], NULL, thread_function, NULL);
    }

    // 提交任务
    for(int i = 0; i < 10; i++) {
        int *arg = malloc(sizeof(int));
        *arg = i;
        submit_task(sample_task, arg);
    }

    sleep(5); // 等待所有任务完成

    // 实际应用中应该有更优雅的退出机制
    return 0;
}

代码分析:

  1. 实现一个简单的线程池,包含任务队列和固定数量的工作线程
  2. 使用互斥锁和条件变量同步任务队列的访问
  3. 工作线程在没有任务时等待条件变量
  4. 提交任务时唤醒等待的工作线程
  5. 每个任务包含一个函数指针和参数

编译和运行

要编译这些多线程程序,需要使用-pthread选项:

gcc program.c -o program -pthread

常见问题及解决方案

  1. 线程创建失败

    • 检查系统资源限制(ulimit -a)
    • 确保没有达到最大线程数限制
  2. 数据竞争

    • 使用互斥锁保护共享数据
    • 考虑使用原子操作或读写锁优化性能
  3. 死锁

    • 避免嵌套锁定多个互斥锁
    • 如果必须锁定多个互斥锁,确保所有线程以相同顺序获取锁
  4. 性能问题

    • 减少临界区范围
    • 考虑使用无锁数据结构
    • 使用线程局部存储减少共享数据
  5. 内存泄漏

    • 确保线程正确退出
    • 使用pthread_joinpthread_detach管理线程资源

这些示例展示了Linux多线程编程的基本概念和技术,包括线程创建、同步、条件变量和线程池实现。在实际应用中,可以根据需求进行调整和扩展。