多线程编程

1. 多线程简单例子

多线程编程是一种在程序中同时执行多个任务的编程方式。它能够有效地利用多核或多处理器的计算资源,提高程序的执行效率。在C语言中,我们可以使用pthread库来进行多线程编程。

pthread库是一个开源的多线程库,它提供了丰富的多线程功能,包括创建、销毁线程、线程同步、线程通信等。下面是一个使用pthread库进行多线程编程的简单例子:

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

// 定义一个函数,该函数将由多个线程执行
void *print_message_function( void *ptr ) {
   char *message;
   message = (char *) ptr;
   printf("%s \n", message);
   pthread_exit(NULL);
}     

int main () {
   pthread_t threads[2];
   char *message1 = "Thread 1";
   char *message2 = "Thread 2";
   
   // 创建两个线程,分别执行print_message_function函数
   pthread_create(&threads[0], NULL, print_message_function, (void*) message1);
   pthread_create(&threads[1], NULL, print_message_function, (void*) message2);
   
   // 等待两个线程完成执行
   for(int i=0; i<2; i++){
        pthread_join(threads[i], NULL);
   }
   
   pthread_exit(NULL);
}

在这个例子中,我们首先定义了一个函数print_message_function,这个函数将会由多个线程执行。然后我们在main函数中创建了两个线程,并且分别传入不同的参数来执行print_message_function函数。每个线程将会打印出对应的消息。最后,我们使用pthread_join函数来等待线程的结束,确保主线程在所有线程结束后退出。

线程池

下面是一个简单的线程池实现例子,它使用了pthread库的各种函数,包括pthread_cond_wait,pthread_cond_broadcast和pthread_mutex_lock等。注意,这只是一个基本的实现,可能需要再进行适应你具体需求的修改。

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

#define MAX_THREADS 5

void *worker(void *arg);

typedef struct one_thread{
    pthread_t thread;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int status;
    int task_params;
}one_thread;


int stop = 0;

int main(void){
    one_thread  *thread_pool = (one_thread*)calloc(MAX_THREADS, sizeof(one_thread));
    int i;

    // init 
    print("========> init thread pool");
    for (i = 0; i < MAX_THREADS; i++){
        pthread_mutex_init(&thread_pool[i].mutex, NULL);
        pthread_cond_init(&thread_pool[i].cond, NULL);
        pthread_create(&thread_pool[i].thread, NULL, worker, (void*)&thread_pool[i]);
    }

    // run task
    print("========> run task");
    for (i = 0; i < 10; i++){
        int thread_idx = i % MAX_THREADS;
        thread_pool[thread_idx].task_params = i;
        thread_pool[thread_idx].status = 0;
        pthread_mutex_lock(&thread_pool[thread_idx].mutex);
        pthread_cond_signal(&thread_pool[thread_idx].cond);
        pthread_mutex_unlock(&thread_pool[thread_idx].mutex);
    }

    
    stop = 1;
    for (i = 0; i < MAX_THREADS; i++){
        pthread_mutex_lock(&thread_pool[i].mutex);
        pthread_cond_broadcast(&thread_pool[i].cond);
        pthread_mutex_unlock(&thread_pool[i].mutex);
    }


    for (i = 0; i < MAX_THREADS; i++){
        pthread_join(thread_pool[i].thread, NULL);
    }

    // detrory thread
    for (i = 0; i < MAX_THREADS; i++){
        pthread_mutex_destroy(&thread_pool[i].mutex);
        pthread_cond_destroy(&thread_pool[i].cond);
    }

    free(thread_pool);


    return 0;
}

void *worker(void *arg){
    one_thread *ctx = (one_thread*)arg;
    while(1){
        pthread_mutex_lock(&ctx->mutex);
        while(!stop && ctx->status == 0){
            pthread_cond_wait(&ctx->cond, &ctx->mutex);
        }
        if(stop){
            pthread_mutex_unlock(&ctx->mutex);
            break;
        }
        printf("Thread %lu did some work, task param = %d \n", pthread_self(), ctx->task_params);
        sleep(1);
        ctx->status = 0;
        pthread_mutex_unlock(&ctx->mutex);
    }

    return NULL;
}

上面的例子创建了5个线程的线程池,

这个程序首先初始化了一个互斥锁和一个条件变量。然后,它创建了五个工作线程,每个线程都等待条件变量被激活。主线程循环10次,每次发出一个信号,唤醒一个等待的线程。然后它休眠一秒,再次循环。最后,主线程发出一个广播信号,唤醒所有等待的线程,然后等待所有线程完成。