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 生产者消费者问题使用锁定和转向变量实现的主要内容,如果未能解决你的问题,请参考以下文章
Go语言编程:使用条件变量Cond和channel通道实现多个生产者和消费者模型
JAVA笔记(20)--- 死锁;如何解决线程安全问题;守护线程;定时器;Callable 实现线程;wait ( ) 和 notify ( ) ;实现生产者和消费者模式;