编程模拟生产者-消费者模型的进程控制(互斥与同步)
1.1、设计目的
- 加深对进程概念的理解,明确进程和程序的区别
- 进一步认识并发执行的实质
- 用信号量的机制实现进程互斥的方法
- 用信号量的机制实现进程同步的方法
1.2、开发环境
window10系统的Dev-C++环境
1.3、原理
其中有三种关系:
①生产者与生产者:互斥
②消费者与消费者:互斥
③生产者与消费者:同步互斥
生产者与消费者模型是基于一个场景,就是生产者在每次生产一个数据必须要放在一个仓库中,而消费者消费必须去仓库中拿数据,这样我们就会产生一些问题,比如,在生产者生产好数据去仓库放东西的时候,消费者是不能进去的,同行消费者取的时候,生产者也不能进去。当仓库为空的时候消费者就得等生产者放数据,仓库满了就必须等消费者取数据。所以为了满足上面的需求,我们就用同步与互斥来进行让他们有效的进行。
1.4、数据与程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex; // 互斥量
pthread_cond_t cond; // 条件
int count = 0; // 用与记录次数
// 用一个链表来当作仓库
typedef struct ListNode
{
struct ListNode* next;
int data;
}ListNode;
ListNode head; // 带头节点
ListNode* CreateNode(int value)
{
ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));
new_node->next = NULL;
new_node->data = value;
return new_node;
}
void Init(ListNode* head)
{
head->data = 0;
head->next = NULL;
}
void Push(ListNode* head, int value)
{
if (head == NULL)
{
return;
}
ListNode* node = CreateNode(value);
ListNode* nex = head->next;
head->next = node;
node->next = nex;
}
void Pop(ListNode* head, int *top)
{
if (head == NULL)
{
return;
}
if (head->next == NULL)
{
return;
}
*top = head->next->data;
ListNode* node = head->next;
head->next = node->next;
free(node);
}
//生产者
void* Producer(void* arg)
{
(void)arg;
while (1)
{
// 加锁
pthread_mutex_lock(&mutex);
Push(&head, count);
printf("Producer %d \n", head.next->data);
++count;
// 产生一个数据,就要唤醒等待的线程
pthread_cond_signal(&cond);
// 解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
return NULL;
}
//消费者
void* Consumer(void* arg)
{
(void)arg;
while (1)
{
int value = -1;
pthread_mutex_lock(&mutex);
// 这里用while是因为有可能被信号打断,
// 当再次返回时候,就可以重新判断
// 也有可能被其它异常信号唤醒
while (head.next == NULL)
{
// 没有数据,就要进行
// 解锁
// 等待
// 加锁
pthread_cond_wait(&cond, &mutex);
}
Pop(&head, &value);
printf("consumer %d\n",value);
pthread_mutex_unlock(&mutex);
usleep(100000);
}
return NULL;
}
int main()
{
Init(&head);
// 初始化
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
// 创建线程
pthread_t producer, consumer;
pthread_create(&producer, NULL, Producer, NULL);
pthread_create(&consumer, NULL, Consumer, NULL);
// 等待线程
pthread_join(producer, NULL);
pthread_join(consumer, NULL);
// 销毁同步与互斥量
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return 0;
}
1.5、程序运行结果
1.6实验总结与心得体会
理解了进程概念,明确了进程和程序之间的区别,进一步认识并发执行的实质。