c_cpp 生产者消费者问题使用锁定和转向变量实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 生产者消费者问题使用锁定和转向变量实现相关的知识,希望对你有一定的参考价值。

/*
 * Producer Consumer Problem using turn variable
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define BUFFERSIZE 100
#define PRODUCER 1
#define CONSUMER 0
#define ITEMS_TO_PRODUCE 500 //To define how many items will be produced
#define ITEMS_TO_CONSUME 500 // To define how many items will be consumed

int p = 1;
int c = 0;
void producer(int *, int *, int *);
void consumer(int *, int *, int *);

int main(int argc, char **argv) {

	int ShmID, ShmID1, bufferId;
	int *count, *turn;
	int *buffer; // Will be the buffer used by producer and consumer
	pid_t pid;
	int status;

	// Creating a Shared Memory Space
	ShmID = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666);
	ShmID1 = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666);
	bufferId = shmget(IPC_PRIVATE, BUFFERSIZE*sizeof(int), IPC_CREAT | 0666);

	if(ShmID<0 || ShmID1<0 || bufferId<0){
		// Will come here if there was error in memory allocation
		printf("Shmget error in server\n");
		exit(1);
	}

	// If program doesn't get into the if condition
	// then the shared space is created successfully


	// Attaching the Shared Memory Space with current process
	count = (int *) shmat(ShmID, NULL, 0);
	turn = (int *) shmat(ShmID1, NULL, 0);
	buffer = (int *) shmat(bufferId, NULL, 0);


	if(count == (int *)-1 || turn==(int *)-1 || buffer==(int *)-1){
		// Will come here if there was error in attaching some memory
		printf("shmat error in server\n");
	}

	// If program is here, then memory attachment successful

	*turn = PRODUCER; // assigning turn to producer process

	pid = fork();

	if(pid==0){
		producer(count, turn, buffer);
		exit(0); // adding this condition so that the forked process exits here
		// and doesn't go any further
	}
	else{
		pid = fork();
		if(pid==0){
			consumer(count, turn, buffer);
			exit(0); //to terminate the fork process exactly after calling the function
		}
	}
	// Waiting for both child processes to terminate
	wait(&status);
	wait(&status);

	shmdt((void *) count); // detaching memory assigned to count
	shmctl(ShmID, IPC_RMID, NULL); //removing memory assigned to count

	shmdt((void *) turn); // detaching memory assigned to turn
	shmdt((void*) buffer); // detaching memory assigned to buffer
	shmctl(ShmID1, IPC_RMID, NULL); //removing memory assigned to turn
	shmctl(bufferId, IPC_RMID, NULL); //removing memory assigned to buffer
}

void producer(int *count, int *turn, int *buffer){
	// Instead of an infine loop
	// We will take a finite loop and produce
	// finite number of
	int i;
	for(i=0;i<ITEMS_TO_PRODUCE;i++){// Producing 1000 items instead of running this as an infinite loop
		int data; // data item to be added to buffer
		data = rand()%1000; // Generating a random value

		while(count[0] == BUFFERSIZE){
			// wait if buffer is full
			// but we also have to make sure that the consumer doesnt stop
			// thats why while we are waiting we'll give consumer a chance to consume
			*turn = CONSUMER; //let consumer consume
		}

		while(*turn==CONSUMER); // Waiting till the other process is in CR
		// Critical Region Starts Here
		*count+=1;
		data = rand()%1000;
		printf("Produced. No. of items in Buffer now: %d\n", *count);
		// Critical Region Ends here
		*turn = CONSUMER; //Exiting CR
	}
	*turn = c;
}

void consumer(int *count, int *turn, int *buffer){	
	// Instead of an infine loop
	// We will take a finite loop and consume
	// finite number of values in buffer 
	int i;
	for(i=0;i<ITEMS_TO_CONSUME;i++){
		// Consuming 500 items instead of making it an infinite loop
	
		while(count[0] == 0){
			// wait till the buffer remains empty
			// but we also have to make sure that the producer doesnt stop
			// production
			*turn = PRODUCER; //let producer produce
		}

		while(*turn==PRODUCER); // Waiting till the other process is in CR
		// Critical Region Starts Here
		*count-=1;
		printf("Consumed. In Buffer now: %d\n", *count);
		// Critical Region Ends here
		*turn = PRODUCER; //Exiting CR
	}
	printf("Consumer done\n");
	*turn = p; // Consumed all items. Giving producer a turn
}
/*
 * pc-lock.c
 *
 *  Created on: Sep 24, 2015
 *      Author: Vikas Yadav (IMT2013060)
 * Producer Consumer Problem using lock variables
 *
 * NOTE:
 *
 * This solution works most of the time properly.
 * Even when the Consumer Process is done executing
 * Producer keeps producing till the buffer is full.
 * Their can be a case of deadlock. Reason explained
 * in the report
 */


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define BUFFERSIZE 1000
#define PRODUCER 1
#define CONSUMER 0
#define true 1
#define false 0
#define br printf("\n")
#define ITEMS_TO_PRODUCE 500 //To define how many items will be produced
#define ITEMS_TO_CONSUME 500 // To define how many items will be consumed

int p = 1;
int c = 0;
void producer(int *, int *, int *);
void consumer(int *, int *, int *);

int main(int argc, char **argv) {

	int ShmID, ShmID1, bufferId;
	int *count, *turn, *flag;
	int *buffer; // Will be the buffer used by producer and consumer
	pid_t pid;
	int status;



	// Creating a Shared Memory Space
	ShmID = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666);
	ShmID1 = shmget(IPC_PRIVATE, 2*sizeof(int), IPC_CREAT | 0666); // to be used as lock variable
	bufferId = shmget(IPC_PRIVATE, BUFFERSIZE*sizeof(int), IPC_CREAT | 0666);

	if(ShmID<0 || ShmID1<0 || bufferId<0){
		// Will come here if there was error in memory allocation
		printf("Shmget error in server\n");
		exit(1);
	}

	// If program doesn't get into the if condition
	// then the shared space is created successfully


	// Attaching the Shared Memory Space with current process
	count = (int *) shmat(ShmID, NULL, 0);
	flag = (int *) shmat(ShmID1, NULL, 0);
	buffer = (int *) shmat(bufferId, NULL, 0);


	if(count == (int *)-1 || flag==(int *)-1 || buffer==(int *)-1){
		// Will come here if there was error in attaching some memory
		printf("shmat error in server\n");
	}

	// If program is here, then memory attachment successful

	flag[PRODUCER] = false;
	flag[CONSUMER] = false; //Initializing both processes as not willing to enter CR;

	pid = fork();

	if(pid==0){
		producer(count, flag, buffer);
		exit(0); // adding this condition so that the forked process exits here
		// and doesn't go any further
	}
	else{
		pid = fork();
		if(pid==0){
			consumer(count, flag, buffer);
			exit(0); //to terminate the fork process exactly after calling the function
		}
	}
	// Waiting for both child processes to terminate
	wait(&status);
	wait(&status);

	shmdt((void *) count); // detaching memory assigned to count
	shmctl(ShmID, IPC_RMID, NULL); //removing memory assigned to count

	shmdt((void *) flag); // detaching memory assigned to turn
	shmdt((void*) buffer); // detaching memory assigned to buffer
	shmctl(ShmID1, IPC_RMID, NULL); //removing memory assigned to turn
	shmctl(bufferId, IPC_RMID, NULL); //removing memory assigned to buffer
}

void producer(int *count, int *flag, int *buffer){
	// Instead of an infine loop
	// We will take a finite loop and produce
	// finite number of
	int i;
	for(i=0;i<ITEMS_TO_PRODUCE;i++){// Producing 1000 items instead of running this as an infinite loop
		int data; // data item to be added to buffer
		data = rand()%1000; // Generating a random value

		while(count[0] == BUFFERSIZE){
			// wait if buffer is full
			// but we also have to make sure that the consumer doesnt stop
			// thats why while we are waiting we'll give consumer a chance to consume
			flag[CONSUMER] = true; //let consumer consume
		}

		flag[PRODUCER] == true; // Producer is willing to enter the CR

		while(flag[CONSUMER]==true); // Waiting till the Consumer is in CR
		// Critical Region Starts Here
		*count+=1;
		data = rand()%1000;
		printf("Produced. No. of items in Buffer now: %d\n", *count);
		// Critical Region Ends here
		flag[PRODUCER] = false; //Exiting CR. Consumer can now enter CR if it wants to
	}
	printf("Producer Done"); br;
}

void consumer(int *count, int *flag, int *buffer){
	// Instead of an infine loop
	// We will take a finite loop and consume
	// finite number of values in buffer
	int i;
	for(i=0;i<ITEMS_TO_CONSUME;i++){
		// Consuming 500 items instead of making it an infinite loop

		while(*count== 0){
			// wait till the buffer remains empty
			// but we also have to make sure that the producer doesnt stop
			// production
			flag[PRODUCER]=true ; //let producer produce
		}

		flag[CONSUMER] = true; // Consumer Process willing to enter CR
		while(flag[PRODUCER]); // Waiting till the producer process is in CR
		// Critical Region Starts Here
		*count-=1;

		printf("Consumed. In Bufer now: %d\n", *count);
		// Critical Region Ends here
		flag[CONSUMER]=false; //Exiting CR
	}
	printf("Consumer done");br;
}

以上是关于c_cpp 生产者消费者问题使用锁定和转向变量实现的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 生产者消费者问题使用锁定和转向变量实现

c_cpp 生产者消费者问题使用锁定和转向变量实现

消费者/生产者锁定 GUI 线程

Go语言编程:使用条件变量Cond和channel通道实现多个生产者和消费者模型

尝试锁定共享内存互斥体时出现分段错误

JAVA笔记(20)--- 死锁;如何解决线程安全问题;守护线程;定时器;Callable 实现线程;wait ( ) 和 notify ( ) ;实现生产者和消费者模式;