线程基础与生产者消费者模型实践

在现代计算领域,多线程编程是提高程序效率和响应性的关键技术之一。本文将深入浅出地介绍线程的基本概念、线程同步机制,特别是互斥锁和条件变量,并通过实现一个经典的“生产者消费者”问题示例来展示这些概念的实际应用

线程基础

线程定义

线程是操作系统调度的最小单位,是进程内的一个执行路径。每个线程拥有独立的栈空间、程序计数器等资源,但共享所属进程的地址空间、全局变量等资源。

线程调度

操作系统通过调度器管理线程的执行,为每个线程分配时间片。时间片的长度直接影响系统的响应性和吞吐量。

线程同步

多线程环境下,为了防止数据竞争和死锁,需要引入同步机制。主要包括互斥锁、信号量、条件变量等。

 互斥锁与条件变量

互斥锁

互斥锁(Mutex)用于保护临界区资源,确保同一时刻只有一个线程可以访问共享资源。例如,pthread_mutex_lock()pthread_mutex_unlock() 函数分别用于加锁和解锁。

条件变量

条件变量(Condition Variable)用于线程间的同步,当线程需要等待某个条件成立时,可以使用条件变量进入休眠,直到其他线程通知条件满足。主要函数包括 pthread_cond_wait()pthread_cond_signal()

生产者消费者问题实例

问题描述

生产者和消费者共享一个固定大小的缓冲区。生产者负责生产数据放入缓冲区,消费者负责消费数据。需解决缓冲区满时生产者的等待以及缓冲区空时消费者的等待问题。

实现代码(C语言,使用POSIX线程库)

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

#define BUFFER_SIZE 10
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 2

int buffer[BUFFER_SIZE];
int in = 0, out = 0;
pthread_mutex_t mutex;
pthread_cond_t not_full, not_empty;

void *producer(void *arg) {
    int data;
    for (;;) {
        data = rand() % 100;
        pthread_mutex_lock(&mutex);
        while (in - out == BUFFER_SIZE) {
            pthread_cond_wait(&not_full, &mutex); // 缓冲区满,等待
        }
        buffer[in % BUFFER_SIZE] = data;
        printf("Produced: %d\n", data);
        in++;
        pthread_cond_signal(&not_empty); // 唤醒消费者
        pthread_mutex_unlock(&mutex);
        usleep(rand() % 1000000); // 模拟生产间隔
    }
    return NULL;
}

void *consumer(void *arg) {
    for (;;) {
        pthread_mutex_lock(&mutex);
        while (in - out == 0) {
            pthread_cond_wait(&not_empty, &mutex); // 缓冲区空,等待
        }
        int data = buffer[out % BUFFER_SIZE];
        printf("Consumed: %d\n", data);
        out++;
        pthread_cond_signal(&not_full); // 唤醒生产者
        pthread_mutex_unlock(&mutex);
        usleep(rand() % 1000000); // 模拟消费间隔
    }
    return NULL;
}

int main() {
    pthread_t producers[NUM_PRODUCERS], consumers[NUM_CONSUMERS];

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&not_full, NULL);
    pthread_cond_init(&not_empty, NULL);

    for (int i = 0; i < NUM_PRODUCERS; ++i) {
        pthread_create(&producers[i], NULL, producer, NULL);
    }
    for (int i = 0; i < NUM_CONSUMERS; ++i) {
        pthread_create(&consumers[i], NULL, consumer, NULL);
    }

    // 理论上应等待所有线程结束,此处简化处理
    sleep(10); // 运行一段时间后手动结束

    for (int i = 0; i < NUM_PRODUCERS; ++i) {
        pthread_join(producers[i], NULL);
    }
    for (int i = 0; i < NUM_CONSUMERS; ++i) {
        pthread_join(consumers[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&not_full);
    pthread_cond_destroy(&not_empty);

    return 0;
}

解释

  • 使用pthread_mutex_lock()pthread_mutex_unlock()来控制对缓冲区的独占访问。
  • 当缓冲区满时,生产者调用pthread_cond_wait()not_full条件变量上等待,直到消费者消费数据后通过pthread_cond_signal()唤醒。
  • 类似地,消费者在缓冲区空时等待在not_empty条件变量上,由生产者完成填充后唤醒。
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值