C语言多线程编程训练指南

多线程编程基础

1. 线程与进程的区别

  • 进程:操作系统资源分配的基本单位,拥有独立的内存空间。

  • 线程:进程内的执行单元,共享同一进程的内存空间,切换开销更小。 一个进程可包含多个线程。

2. 线程的创建与生命周期

  • 创建:通过pthread_create()函数定义线程。

  • 终止:自然结束(函数返回)或显式调用pthread_exit()

  • 回收资源:父线程通过pthread_join()等待子线程结束。

3. 线程同步机制

  • 互斥锁(Mutex):保护共享资源,避免数据竞争。

  • 条件变量(Condition Variable):线程间通信,基于特定条件唤醒等待线程。

  • 信号量(Semaphore):控制对共享资源的并发访问数量。

注意:在编译多线程程序时需链接pthread库:

gcc program.c -o program -lpthread

多线程编程训练题

以下是从基础到进阶的多线程编程题目,涵盖线程操作、同步机制与并发控制。


1. 简单线程创建与参数传递

题目描述 创建两个线程,分别打印传入的整数值(如10和20)。主线程等待子线程结束后输出All threads completed

示例输出

Thread 1 value: 10
Thread 2 value: 20
All threads completed

参考代码

#include <stdio.h>
#include <pthread.h>
​
void* print_value(void* arg) {
    int value = *(int*)arg;
    printf("Thread value: %d\n", value);
    pthread_exit(NULL);
}
​
int main() {
    pthread_t t1, t2;
    int val1 = 10, val2 = 20;
    pthread_create(&t1, NULL, print_value, &val1);
    pthread_create(&t2, NULL, print_value, &val2);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("All threads completed\n");
    return 0;
}

2. 多线程计算数组和

题目描述 将一个数组分为两部分,由两个线程分别计算各部分的累加和,主线程汇总后输出总和。

示例输入 数组:[1, 2, 3, 4, 5, 6] 示例输出

Total sum: 21

参考代码

#include <stdio.h>
#include <pthread.h>
​
#define ARRAY_SIZE 6
int sum = 0;
pthread_mutex_t mutex;
​
typedef struct {
    int* array;
    int start;
    int end;
} ThreadData;
​
void* partial_sum(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    int local_sum = 0;
    for (int i = data->start; i < data->end; i++) {
        local_sum += data->array[i];
    }
    pthread_mutex_lock(&mutex);
    sum += local_sum;
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
​
int main() {
    int arr[ARRAY_SIZE] = {1, 2, 3, 4, 5, 6};
    pthread_t t1, t2;
    ThreadData d1 = {arr, 0, ARRAY_SIZE/2};
    ThreadData d2 = {arr, ARRAY_SIZE/2, ARRAY_SIZE};
​
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&t1, NULL, partial_sum, &d1);
    pthread_create(&t2, NULL, partial_sum, &d2);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_mutex_destroy(&mutex);
    printf("Total sum: %d\n", sum);
    return 0;
}

3. 生产者-消费者问题(条件变量)

题目描述 实现一个生产者-消费者模型:

  • 生产者线程生成1~100的数字存入缓冲区。

  • 消费者线程从缓冲区取出数字并打印。

  • 缓冲区大小为5,满时生产者等待,空时消费者等待。

示例输出片段

Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
...

参考代码框架

#include <stdio.h>
#include <pthread.h>
​
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE], count = 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) {
    for (int i = 1; i <= 100; i++) {
        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE) 
            pthread_cond_wait(&cond_producer, &mutex);
        buffer[count++] = i;
        printf("Produced: %d\n", i);
        pthread_cond_signal(&cond_consumer);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
​
void* consumer(void* arg) {
    for (int i = 0; i < 100; i++) {
        pthread_mutex_lock(&mutex);
        while (count == 0) 
            pthread_cond_wait(&cond_consumer, &mutex);
        int num = buffer[--count];
        printf("Consumed: %d\n", num);
        pthread_cond_signal(&cond_producer);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
​
int main() {
    pthread_t t1, t2;
    pthread_create(&t1, NULL, producer, NULL);
    pthread_create(&t2, NULL, consumer, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

4. 互斥锁实现线程安全计数器

题目描述 创建4个线程,每个线程对全局计数器累加2500次,确保最终结果为10000。使用互斥锁防止数据竞争。

示例输出

Final counter value: 10000

参考代码

#include <stdio.h>
#include <pthread.h>
​
#define THREADS 4
#define INCREMENTS 2500
int counter = 0;
pthread_mutex_t mutex;
​
void* increment(void* arg) {
    for (int i = 0; i < INCREMENTS; i++) {
        pthread_mutex_lock(&mutex);
        counter++;
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
​
int main() {
    pthread_t threads[THREADS];
    pthread_mutex_init(&mutex, NULL);
    for (int i = 0; i < THREADS; i++) 
        pthread_create(&threads[i], NULL, increment, NULL);
    for (int i = 0; i < THREADS; i++)
        pthread_join(threads[i], NULL);
    pthread_mutex_destroy(&mutex);
    printf("Final counter value: %d\n", counter);
    return 0;
}

5. 信号量实现读者-写者问题

题目描述 用信号量实现读者优先的读者-写者模型:

  • 允许多个读者同时读取共享资源。

  • 写者必须独占访问资源。

参考框架

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
​
sem_t rw_mutex, mutex;
int readers = 0;
​
void* reader(void* arg) {
    sem_wait(&mutex);
    readers++;
    if (readers == 1) sem_wait(&rw_mutex); // 第一个读者锁住写者
    sem_post(&mutex);
​
    // 读取操作...
​
    sem_wait(&mutex);
    readers--;
    if (readers == 0) sem_post(&rw_mutex); // 最后一个读者释放写者
    sem_post(&mutex);
    return NULL;
}
​
void* writer(void* arg) {
    sem_wait(&rw_mutex);
    // 写入操作...
    sem_post(&rw_mutex);
    return NULL;
}
​
int main() {
    sem_init(&rw_mutex, 0, 1);
    sem_init(&mutex, 0, 1);
    // 创建读者和写者线程...
    return 0;
}

进阶挑战

6. 动态线程池实现

题目描述 实现一个线程池:主线程提交任务到任务队列,空闲线程从队列中取出任务执行。支持动态调整线程数量。

关键步骤

  1. 使用队列存储任务(函数指针+参数)。

  2. 动态创建/销毁线程。

  3. 通过互斥锁和条件变量管理任务队列。


训练总结

通过以上题目,可掌握C语言中:

  1. 基本的线程创建与管理。

  2. 互斥锁、条件变量、信号量的使用场景。

  3. 经典并发问题(如生产者-消费者、读者-写者)的解决方案。

  4. 多线程程序调试技巧(死锁分析、竞态条件检查)。 建议结合调试工具(如Valgrind)确保线程安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值