【C语言】生产者消费者问题linux与windows兼容

代码描述

NOTES:
一共有3个线程:main thread、producer、consumer
main thread:读取command line paramters 运送到与生产者共享的buffer1
producer thread:从buffer1中取数据,进行加工factorNumber,再运送至与消费者共享的buffer2
consumer thread:从buffer2中取数据(消费),并展示加工的结果。

说明

buffer1为一维数组,buffer2为二维指针数组
代码还需在内存申请方面进行优化,不过我严格了限制条件,producer与consumer只会本分的工作,consumer消费完所有参数就会退出,以防内存泄漏。
优化思路:buffer的动态内存申请、race condition的优化、buffer考虑用结构体等。

代码性能

buffer1与buffer2标准size为50,经过调优可以将buffer1的size设置为2,buffer2的size设置为2,线程可处理2000个命令行参数(因为define 了 argc的最大值),即使将argcMAX调大也可正常运行,BINGGO!

Makefile文件

#MakeFile 
CC=gcc
CFLAGS=-Wall -g -MMD -MP
INCLUDES=-I ./include
ALLOC_LINK=-ldl -lrt -lpthread

main: main.o producer.o consumer.o prodcons.o
	$(CC) $(INCLUDES) $(CFLAGS) -o $@ $^ $(ALLOC LINK)
	-mkdir -p bin
	mv $@ bin -f
main.o:main.c
	$(CC) -C $(INCLUDES) $(CFLAGS) main.c
producer.o: producer.c
	$(CC) -C $(INCLUDES) $(CFLAGS) producer.c
consumer.o:consumer.c
	$(CC) -C $(INCLUDES) $(CFLAGS) consumer.c 
prodcons.o:prodcons.c
	$(CC) -C $(INCLUDES) $(CFLAGS) prodcons.c
clean: 
	rm -f main.0 producer.o consumer.o prodcons.o
	rm -f main.d producer.d consumer.d prodcons.d
	rm -f bin/main

代码:

//main.c
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include"prodcons.h"
#include"consumer.h"
#include"producer.h"
#include"string.h"
#define _GNU_SOURCE

//#pragma comment(lib, "pthreadVC2.lib")

void* mainthread(void* data)
{
	//main thread
	int num = 0;
	int *input = data;
	while (1)
	{
		//race condition
		while (counter == BUFFER_SIZE1)
			;//do nothing
		pthread_mutex_lock(&mutex1);

		if (num < argvcounter)
		{
			buffer[in] = input[num];
			in = (in + 1) % BUFFER_SIZE1;
			counter++;
			num++;
		}
		
		pthread_mutex_unlock(&mutex1);
	}
}


int main(int argc, char* argv[]) {
	
	//no command line
	if (argc == 1)
	{
		fprintf(stderr,"usage: ./assn4 <number to factor>...\n");
		return -1;
	}
	else {
		for (int i = 1; i < argc; ++i)
		{
			if (atoi(argv[i]) < 0)
			{
				fprintf(stderr, "command line paramters must be >= 0\n");
				return -1;
			}
		}
		
	}
	//handle command line parameters
	int *inputParam = (int*)malloc(sizeof(int));
	if (argc == 2 && *argv[1] == '{')
	{
		char* p = argv[1];
		char* ptr = NULL;
		char* re = NULL;
		int begin = 0, end = 0;
		if (argc == 2 && *argv[1] == '{')
		{
			p++;
			begin = atoi(p);
			re = strtok_s(p, "..", &ptr);
			re = strtok_s(NULL, "..", &ptr);
			end = atoi(re);
		}
		int j = 0;
		for (int i = begin; i <= end; ++i)
		{
			inputParam = realloc(inputParam, (j + 1) * sizeof(int));
			inputParam[j] = i;
			j++;
		}
		argvcounter = (end - begin)+1;
	}
	else
	{
		int x = 0;
		for (int i = 1; i < argc; ++i)
		{
			inputParam = realloc(inputParam, (x + 1) * sizeof(int));
			inputParam[x] = atoi(argv[i]);
			++x;
		}
		argvcounter = argc - 1;
	}
	

	pthread_t child1;
	pthread_t child2;
	pthread_t child3;

	
	counter = 0;
	in = 0;
	out = 0;
	bp_out = 0, bp_in = 0, bp_count = 0;
	int ini1 = pthread_mutex_init(&mutex1, NULL);
	int ini2 = pthread_mutex_init(&mutex2, NULL);
	if (ini1 != 0 || ini2 != 0)
	{
		printf("mutex init failed \n");
		exit(1);
	}

	pthread_create(&child1, NULL, mainthread, inputParam);
	pthread_create(&child2, NULL, producer, NULL);
	pthread_create(&child3, NULL, consumer, NULL);

	//destroy all threads and free BUffer
	pthread_join(child1, NULL);
	pthread_join(child2, NULL);
	pthread_join(child3, NULL);
	free(inputParam);
	free(BufferPool);

	return 0;
}
//producer.c
#include<stdio.h>
#include<stdlib.h>
#include"producer.h"
//facror number
void factor2pc(int* p, int number)
{

	int i, j = 1;
	p[0] = number;
	if (number == 0 ||number == 1)
	{
		//p = realloc(p, 2*sizeof(int));
		p[1] = number;
		return NULL;
	}
	for (i = 2; i <= number; i++) {
		while (number % i == 0) {
			//p = realloc(p, (j + 1) * sizeof(int));
			p[j] = i;
			++j;
			number /= i;
		}
	}
	return NULL;
}
void* producer(void* data)
{
	while (1)
	{
		
		int temp = -1;
		//buffer which save each factor number
		int *Tempbuffer = (int*)malloc(sizeof(int) * ARGVMAX);

		//race condition
		while (counter == 0);
		pthread_mutex_lock(&mutex1);//with the main thread
		//critical area
		temp = buffer[out];
		out = (out + 1) % BUFFER_SIZE1;
		counter--;
		pthread_mutex_unlock(&mutex1);
		
		//factor number
		factor2pc(Tempbuffer, temp);
		
		//race condition
		while (bp_count == BUFFER_SIZE2);
		pthread_mutex_lock(&mutex2);//with the consumer thread
		//critical area
		BufferPool[bp_in] = Tempbuffer;
		bp_in = (bp_in + 1) % BUFFER_SIZE2;
		bp_count++;
		
		pthread_mutex_unlock(&mutex2);

		//free(Tempbuffer);
	}

}
//consumer.c
#include<stdio.h>
#include<stdlib.h>
#include"consumer.h"


void* consumer(void* data) {
	int limit = 0;
	while (1)
	{
		int i = 0, Numberlimit;
		if (limit >= argvcounter)
		{
			exit(-1);
		}
		//race condition
		while (bp_count == 0);
		
		pthread_mutex_lock(&mutex2);
		//make sure the output format is correct
		if (bp_out < argvcounter)
		{
			printf("%d:",(*BufferPool[bp_out])[0]);
			i++;
			Numberlimit = (*BufferPool[bp_out])[0];
			while (i < ARGVMAX)
			{
				//limit condition
				if ((*BufferPool[bp_out])[i] < 0 || (*BufferPool[bp_out])[i] > Numberlimit) break;
				printf("%d ", (*BufferPool[bp_out])[i]);
				++i;
			}
			++limit;
			printf("\n");
			bp_out = (bp_out + 1) % BUFFER_SIZE2;
			bp_count--;
		}
		pthread_mutex_unlock(&mutex2);
	}

}
//producer.h
#ifndef PRODUCER
#define PRODUCER
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include"prodcons.h"
#define BUFFER_SIZE1 (20)//smaller buffer size 
#define MAX 100

//the buffer jointly owned by producer and the main thread
int buffer[BUFFER_SIZE1];
int in, out;
int counter;
int argvcounter;
pthread_mutex_t mutex1;

void factor2pc(int *p, int number);
void* producer(void* data);

#endif
//prodcons.h
#pragma once
#ifndef PRODCONS
#define PRODCONS


#include<pthread.h>
#define BUFFER_SIZE2 (2)// when finished, can try size 2 for fun
#define ARGVMAX 2000
//the BufferPool jointly owned by producer and consumer
int (*BufferPool[BUFFER_SIZE2])[ARGVMAX];
int bp_in, bp_out, bp_count;
pthread_mutex_t mutex2;

#endif
//consumer.h
#pragma once
#ifndef CONSUMER
#define CONSUMER
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include"prodcons.h"
#include"producer.h"
void* consumer(void* data); 
#endif

控制台输出:

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值