标签:
实验报告
一、实验目的
1.熟悉临界资源、信号量及PV操作的定义与物理意义
2.了解进程通信的方法
3.掌握进程互斥与同步的相关知识
4.掌握用信号量机制解决进程之间的同步与互斥问题
5.实现生产者-消费者问题,深刻理解进程同步问题
二、实验环境
Linux系统
三、实验内容
在Linux操作系统下用C或C++实现经典同步问题:生产者-消费者问题,具体要求如下:
1. 一个大小为10的缓冲区,初始状态为空。
2. 2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据之后再添加,重复10次。
3. 2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数据之后再读取,重复10次。
四、程序实现
1.程序中使用的数据结构及说明
1.1缓冲区
缓冲区采用循环队列表示,利用头、尾指针来存放、读取数据,以及判断队列是否为空。缓冲区中数组大小为10。
#define BUFFERNUM 10
//缓冲区队列
struct Buffer_Queue {
char production[BUFFERNUM]; //产品
int front, rear; //头指针和尾指针
int num; //缓冲区里面字母数量
};
1.2信号量
相关信号量的定义采用semaphore.h里面附带的结构
/*信号量*/
//空的信号量和满的信号量
sem_t empty_sem, full_sem;
//静态创建条件变量
pthread_cond_t full = PTHREAD_COND_INITIALIZER; //满的变量
pthread_cond_t empty = PTHREAD_COND_INITIALIZER; //空的变量
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //互斥锁
2.核心算法
2.1生产者
void *producer(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == BUFFERNUM) //缓冲区已经满了,等待
{
pthread_cond_wait(&full, &lock);
}
sem_wait(&empty_sem);
/*生产产品*/
char c = getRandChar(); //随机获取字母
q->rear = (q->rear + 1) % BUFFERNUM; //计算新的尾指针
q->production[q->rear] = c; //写入新产品
q->num++;
sem_post(&full_sem);
if (q->num == 1) {
pthread_cond_signal(&empty);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
2.2消费者
void *consumer(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == 0) //缓冲区已经空了,等待
{
pthread_cond_wait(&empty, &lock);
}
sem_wait(&full_sem);
/*消费产品*/
q->front = (q->front + 1) % BUFFERNUM; //计算新的头指针
char c = q->production[q->front]; //消费产品
q->production[q->front] = ‘ ‘; //
q->num--;
sem_post(&empty_sem);
if (q->num == BUFFERNUM - 1) {
pthread_cond_signal(&full);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
3.源程序及注释
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <time.h>
/*信号量*/
//空的信号量和满的信号量
sem_t empty_sem, full_sem;
//静态创建条件变量
pthread_cond_t full = PTHREAD_COND_INITIALIZER; //满的变量
pthread_cond_t empty = PTHREAD_COND_INITIALIZER; //空的变量
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //互斥锁
#define BUFFERNUM 10
//缓冲区队列
struct Buffer_Queue {
char production[BUFFERNUM]; //产品
int front, rear; //头指针和尾指针
int num; //缓冲区里面字母数量
};
//输出设计者信息
void printDesign()
{
printf(" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
printf(" ┃ 生产者-消费者问题实现 ┃\n");
printf(" ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n");
}
//随机产生生产字符
char getRandChar()
{
int temp = rand()%26;
return (‘a‘+temp);
}
//打印进程运行结果
void printTime()
{
//打印时间
time_t now;
struct tm *timenow; //实例化tm结构指针
time(&now);
timenow = localtime(&now);
printf("执行时间: %s ",asctime(timenow));
}
//生产者1
void *producer1(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == BUFFERNUM) //缓冲区已经满了,等待
{
pthread_cond_wait(&full, &lock);
}
sem_wait(&empty_sem);
/*生产产品*/
char c = getRandChar(); //随机获取字母
q->rear = (q->rear + 1) % BUFFERNUM; //计算新的尾指针
q->production[q->rear] = c; //写入新产品
q->num++;
/*打印输出结果*/
printf("-------------------------------------------------------------\n");
printTime(); //程序运行时间
int i;
printf("缓冲区数据(%d个):",q->num); //打印缓冲区中的数据
if(q->front < q->rear)
{
for(i = q->front; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
else
{
for(i = q->front; i < BUFFERNUM; i++)
printf("%c ",q->production[i]);
for(i = 0; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
printf("\n当前执行的进程:生产者1\n"); //打印当前执行的进程
printf("产生的数据:%c\n",c); //打印产生或消费的数据
printf("-------------------------------------------------------------\n");
sem_post(&full_sem);
if (q->num == 1) {
pthread_cond_signal(&empty);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
//生产者2
void *producer2(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == BUFFERNUM) //缓冲区已经满了,等待
{
pthread_cond_wait(&full, &lock);
}
sem_wait(&empty_sem);
/*生产产品*/
char c = getRandChar(); //随机获取字母
q->rear = (q->rear + 1) % BUFFERNUM; //计算新的尾指针
q->production[q->rear] = c; //写入新产品
q->num++;
/*打印输出结果*/
printf("-------------------------------------------------------------\n");
printTime(); //程序运行时间
int i;
printf("缓冲区数据(%d个):",q->num); //打印缓冲区中的数据
if(q->front < q->rear)
{
for(i = q->front; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
else
{
for(i = q->front; i < BUFFERNUM; i++)
printf("%c ",q->production[i]);
for(i = 0; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
printf("\n当前执行的进程:生产者2\n"); //打印当前执行的进程
printf("产生的数据:%c\n",c); //打印产生或消费的数据
printf("-------------------------------------------------------------\n");
sem_post(&full_sem);
if (q->num == 1) {
pthread_cond_signal(&empty);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
//消费者1
void *consumer1(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == 0) //缓冲区已经空了,等待
{
pthread_cond_wait(&empty, &lock);
}
sem_wait(&full_sem);
/*消费产品*/
q->front = (q->front + 1) % BUFFERNUM; //计算新的头指针
char c = q->production[q->front]; //消费产品
q->production[q->front] = ‘ ‘; //
q->num--;
/*打印输出结果*/
printf("-------------------------------------------------------------\n");
printTime(); //程序运行时间
int i;
printf("缓冲区数据(%d个):",q->num); //打印缓冲区中的数据
if(q->front < q->rear)
{
for(i = q->front; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
else
{
for(i = q->front; i < BUFFERNUM; i++)
printf("%c ",q->production[i]);
for(i = 0; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
printf("\n当前执行的进程:消费者1\n"); //打印当前执行的进程
printf("消耗的数据:%c\n",c); //打印产生或消费的数据
printf("-------------------------------------------------------------\n");
sem_post(&empty_sem);
if (q->num == BUFFERNUM - 1) {
pthread_cond_signal(&full);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
//消费者2
void *consumer2(void *arg)
{
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) arg;
while(1)
{
pthread_mutex_lock(&lock);
while (q->num == 0) //缓冲区已经空了,等待
{
pthread_cond_wait(&empty, &lock);
}
sem_wait(&full_sem);
/*消费产品*/
q->front = (q->front + 1) % BUFFERNUM; //计算新的头指针
char c = q->production[q->front]; //消费产品
q->production[q->front] = ‘ ‘; //
q->num--;
/*打印输出结果*/
printf("-------------------------------------------------------------\n");
printTime(); //程序运行时间
int i;
printf("缓冲区数据(%d个):",q->num); //打印缓冲区中的数据
if(q->front < q->rear)
{
for(i = q->front; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
else
{
for(i = q->front; i < BUFFERNUM; i++)
printf("%c ",q->production[i]);
for(i = 0; i <= q->rear; i++)
printf("%c ",q->production[i]);
}
printf("\n当前执行的进程:消费者1\n"); //打印当前执行的进程
printf("消耗的数据:%c\n",c); //打印产生或消费的数据
printf("-------------------------------------------------------------\n");
sem_post(&empty_sem);
if (q->num == BUFFERNUM - 1) {
pthread_cond_signal(&full);
}
pthread_mutex_unlock(&lock);
sleep(rand() % 2);
}
}
int main(int argc, char *argv[])
{
//输出设计者
printDesign();
/*创建缓冲区*/
//定义
struct Buffer_Queue *q;
q = (struct Buffer_Queue *) malloc(sizeof(struct Buffer_Queue));
//初始化队列
q->front = q->rear = BUFFERNUM - 1;
q->num = 0;
/*执行进程*/
//定义四个线程
pthread_t pid1, cid1, pid2, cid2;
//初始化信号量
sem_init(&empty_sem, 0, BUFFERNUM);
sem_init(&full_sem, 0, 0);
//创建线程
pthread_create(&pid1, NULL, producer1, (void *) q);
pthread_create(&cid1, NULL, consumer1, (void *) q);
pthread_create(&pid2, NULL, producer2, (void *) q);
pthread_create(&cid2, NULL, consumer2, (void *) q);
//销毁线程
pthread_join(pid1, NULL);
pthread_join(cid1, NULL);
pthread_join(pid2, NULL);
pthread_join(cid2, NULL);
//销毁信号量
sem_destroy(&empty_sem);
sem_destroy(&full_sem);
return 0;
}
五、运行结果
1.linux环境下,用gcc编译
1.1编译
1.2执行结果
截图1
截图2
截图3
标签:
原文地址:http://www.cnblogs.com/txf1949/p/4484114.html