#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define _NR_gettid 186 //system call to get the threadid #define BUFFER_SIZE 10 typedef int buffer_item; buffer_item buffer[BUFFER_SIZE]; sem_t empty; sem_t full; sem_t mutex; int insertPointer = 0, removePointer = 0; void *producer(void *param); void *consumer(void *param); int main(int argc, char *argv[]) { int sleepTime, producerThreads, consumerThreads; int i, j; if(argc != 4) { fprintf(stderr, "usage: <waiting time for parent> <num of producer> <num of consumer>\n"); return -1; } sleepTime = atoi(argv[1]); producerThreads = atoi(argv[2]); consumerThreads = atoi(argv[3]); /* Initialize the synchronization tools */ sem_init(&mutex, 0, 1); sem_init(&empty, 0, BUFFER_SIZE); sem_init(&full, 0, 0); srand(time(0)); /* Create the producer and consumer threads */ for(i = 0; i < producerThreads; i++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, producer, NULL); } for(j = 0; j < consumerThreads; j++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, consumer, NULL); } /* Sleep for user specified time */ sleep(sleepTime); return 0; } void *producer(void *param) { buffer_item random; int r,i=0; int numofproduction=5; while(i<numofproduction) { r = rand() % 5; sleep(r); random = rand(); sem_wait(&empty); sem_wait(&mutex); buffer[insertPointer] = random; //print in red printf("\033[47;31mproducer%ld in buffer%d. %dth produce like: %d\n\033[0m", (long int)syscall(_NR_gettid), insertPointer,i, random); insertPointer = (insertPointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&full); i++; } } void *consumer(void *param) { buffer_item random; int r,j=0; int numofconsumption=5;while(j<numofconsumption) { r = rand() % 5; sleep(r); sem_wait(&full); sem_wait(&mutex); random = buffer[removePointer]; printf("consumer%ld in buffer%d. %dth consume like: %d\n", (long int)syscall(_NR_gettid),removePointer,j,random); removePointer = (removePointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&empty); j++; } }
理解问题#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define _NR_gettid 186 //system call to get the threadid #define BUFFER_SIZE 10 typedef int buffer_item; buffer_item buffer[BUFFER_SIZE]; sem_t empty; sem_t full; sem_t mutex; int insertPointer = 0, removePointer = 0; void *producer(void *param); void *consumer(void *param); int main(int argc, char *argv[]) { int sleepTime, producerThreads, consumerThreads; int i, j; if(argc != 4) { fprintf(stderr, "usage: <waiting time for parent> <num of producer> <num of consumer>\n"); return -1; } sleepTime = atoi(argv[1]); producerThreads = atoi(argv[2]); consumerThreads = atoi(argv[3]); /* Initialize the synchronization tools */ sem_init(&mutex, 0, 1); sem_init(&empty, 0, BUFFER_SIZE); sem_init(&full, 0, 0); srand(time(0)); /* Create the producer and consumer threads */ for(i = 0; i < producerThreads; i++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, producer, NULL); } for(j = 0; j < consumerThreads; j++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, consumer, NULL); } /* Sleep for user specified time */ sleep(sleepTime); return 0; } void *producer(void *param) { buffer_item random; int r,i=0; int numofproduction=5; while(i<numofproduction) { r = rand() % 5; sleep(r); random = rand(); sem_wait(&empty); sem_wait(&mutex); buffer[insertPointer] = random; //print in red printf("\033[47;31mproducer%ld in buffer%d. %dth produce like: %d\n\033[0m", (long int)syscall(_NR_gettid), insertPointer,i, random); insertPointer = (insertPointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&full); i++; } } void *consumer(void *param) { buffer_item random; int r,j=0; int numofconsumption=5;while(j<numofconsumption) { r = rand() % 5; sleep(r); sem_wait(&full); sem_wait(&mutex); random = buffer[removePointer]; printf("consumer%ld in buffer%d. %dth consume like: %d\n", (long int)syscall(_NR_gettid),removePointer,j,random); removePointer = (removePointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&empty); j++; } }
已完成理解「#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define _NR_gettid 186 //system call to get the threadid #define BUFFER_SIZE 10 typedef int buffer_item; buffer_item buffer[BUFFER_SIZE]; sem_t empty; sem_t full; sem_t mutex; int insertPointer = 0, removePointer = 0; void *producer(void *param); void *consumer(void *param); int main(int argc, char *argv[]) { int sleepTime, producerThreads, consumerThreads; int i, j; if(argc != 4) { fprintf(stderr, "usage: <waiting time for parent> <num of producer> <num of consumer>\n"); return -1; } sleepTime = atoi(argv[1]); producerThreads = atoi(argv[2]); consumerThreads = atoi(argv[3]); /* Initialize the synchronization tools */ sem_init(&mutex, 0, 1); sem_init(&empty, 0, BUFFER_SIZE); sem_init(&full, 0, 0); srand(time(0)); /* Create the producer and consumer threads */ for(i = 0; i < producerThreads; i++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, producer, NULL); } for(j = 0; j < consumerThreads; j++) { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid, &attr, consumer, NULL); } /* Sleep for user specified time */ sleep(sleepTime); return 0; } void *producer(void *param) { buffer_item random; int r,i=0; int numofproduction=5; while(i<numofproduction) { r = rand() % 5; sleep(r); random = rand(); sem_wait(&empty); sem_wait(&mutex); buffer[insertPointer] = random; //print in red printf("\033[47;31mproducer%ld in buffer%d. %dth produce like: %d\n\033[0m", (long int)syscall(_NR_gettid), insertPointer,i, random); insertPointer = (insertPointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&full); i++; } } void *consumer(void *param) { buffer_item random; int r,j=0; int numofconsumption=5;while(j<numofconsumption) { r = rand() % 5; sleep(r); sem_wait(&full); sem_wait(&mutex); random = buffer[removePointer]; printf("consumer%ld in buffer%d. %dth consume like: %d\n", (long int)syscall(_NR_gettid),removePointer,j,random); removePointer = (removePointer+1) % BUFFER_SIZE ; sem_post(&mutex); sem_post(&empty); j++; } }」
展开阅读网页
这段代码是Linux环境下使用C语言实现的生产者-消费者问题的多线程解决方案。1
🔧 功能实现
- 多线程同步:通过
pthread
库创建多个生产者和消费者线程,利用信号量sem_t
和互斥锁mutex
实现线程间的同步和互斥。1 - 缓冲区管理:使用固定大小的数组
buffer
模拟缓冲区,通过insertPointer
和removePointer
分别控制生产者和消费者对缓冲区的访问。1
📝 主要流程
- 初始化同步工具:初始化互斥锁
mutex
、表示空缓冲区数量的信号量empty
和表示满缓冲区数量的信号量full
。 - 创建线程:根据用户输入创建指定数量的生产者和消费者线程。
- 生产者逻辑:生产者在生成数据后,先等待空缓冲区,然后锁定互斥锁,将数据放入缓冲区,最后释放互斥锁并增加满缓冲区信号量。
- 消费者逻辑:消费者从缓冲区获取数据前,先等待满缓冲区,然后锁定互斥锁,从缓冲区取出数据,最后释放互斥锁并增加空缓冲区信号量。
🚀 运行效果
- 生产者和消费者线程交替运行,生产者生成随机数并放入缓冲区,消费者从缓冲区取出数据并打印,模拟了生产者-消费者问题的实际场景。1
这段代码是一个使用C语言在Linux环境下实现的生产者-消费者问题的多线程解决方案。它利用了POSIX线程库(pthread)和信号量(semaphore)来实现线程间的同步和互斥操作。生产者线程负责生成数据并将其放入缓冲区,而消费者线程则从缓冲区中取出数据进行处理。以下是对代码的详细分析和一些可能的改进建议。
😊线程同步机制
- 信号量用于同步:代码中使用了三个信号量:
empty
、full
和mutex
。empty
和full
分别用来跟踪缓冲区中空位和满位的数量,而mutex
则用于确保对缓冲区的互斥访问。这种同步机制确保了生产者不会在缓冲区满时向其添加数据,消费者也不会在缓冲区空时尝试从中取数据。12
😊缓冲区的实现
- 循环缓冲区:缓冲区使用了一个固定大小的数组
buffer
来实现,并通过insertPointer
和removePointer
两个指针来分别跟踪生产者和消费者的位置。当任一指针达到数组末尾时,会循环回到数组的开始位置,形成一个循环缓冲区。这种设计允许多个生产者和消费者线程高效地共享缓冲区资源。3
😊线程的创建和管理
- 动态创建线程:代码中根据用户输入动态创建了指定数量的生产者和消费者线程。每个线程在创建时都会调用相应的生产者或消费者函数。这种动态创建线程的方式提高了程序的灵活性和可扩展性。4
😊线程同步的挑战
- 死锁和竞态条件:尽管代码使用了信号量来同步线程,但在多线程环境中,死锁和竞态条件仍然是需要关注的问题。例如,如果两个线程同时尝试获取同一个资源,可能会导致死锁。此外,如果多个线程同时访问共享资源而没有适当的同步机制,可能会导致竞态条件。78
😊性能优化
- 减少锁的竞争:在当前的实现中,每次生产者或消费者访问缓冲区时都需要获取和释放
mutex
锁,这可能会导致锁的竞争和性能瓶颈。一种可能的优化方法是减少对锁的依赖,例如通过使用原子操作或无锁编程技术来实现线程安全的共享数据结构。9
😊代码的健壮性
- 异常处理:在多线程程序中,异常处理尤为重要。当前的代码中没有显式地处理线程创建失败或信号量操作失败的情况。在实际应用中,应该添加必要的异常处理代码,以确保程序在遇到错误时能够优雅地处理并提供有用的错误信息。10
总结来说,这段代码提供了一个基本的生产者-消费者问题的多线程解决方案,通过使用信号量和循环缓冲区来实现线程间的同步和互斥。然而,在实际应用中,还需要考虑死锁、竞态条件、性能优化和异常处理等方面的问题,以确保程序的健壮性和高效性。