实现信号量版本的生产者和消费者模型(多线程)
【摘要】 6.8 实现信号量版本的生产者和消费者模型(多线程)#include<stdio.h>#include<string.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#include<semaphore.h>//生产者与消费者信号量模型//连表节点类型typedef struct _node_t{ int date; ...
6.8 实现信号量版本的生产者和消费者模型(多线程)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
//生产者与消费者信号量模型
//连表节点类型
typedef struct _node_t
{
int date; //数据类
struct _node_t* next; //指针域
}node_t;
node_t* head = NULL; //头节点
sem_t sem_customer; //可以卖产品的个数
sem_t sem_producer;//容器的个数
//生产者
void* producer(void *arg)
{
node_t* new = NULL; //新节点
//申请一个资源 容器
sem_wait(&sem_producer);
//循环生产产品
while(1)
{
//申请一个资源,容器
sem_wait(&sem_producer);
new = malloc(sizeof(node_t)); //分配节点空间(使用堆会出现不可重入,需要使用锁)
if(new == NULL)
{
printf("malloc failed.../n");
}
memset(new,0,sizeof(node_t));
new->date = random()%100+1;//赋值:1-100
new->next = NULL;
printf("生产者生产产品:%d\n",new->date);
//头插法
new->next = head;
head = new;
//通知消费者消费 将可以卖的商品个数加1
sem_post(&sem_customer);
sleep(random()%3+1);//随机睡眠1-3秒
}
pthread_exit(NULL);
}
//消费者线程
void *customer(void* arg)
{
node_t* tmp = NULL; //临时节点
//循环消费
while(1)
{
//申请资源 可以卖的商品个数减1
sem_wait(&sem_customer);
//链表为空的情形
if(head == NULL)
{
printf("产品链表为空,先休息2秒钟...\n");
}
//第一个节点地址赋值给临时变量tmp
tmp = head;
//head指向链表的第二个节点
head = head->next;
printf("消费者消耗产品:%d\n",tmp->date);
free(tmp); //释放空间
//释放一个资源,将容器个数加1
sem_post(&sem_producer);
sleep(random()%3+1);//随机睡眠1-3秒
}
return NULL;
}
//生产者和消费者模型 信号变量的模型
int main(void)
{
int ret = -1;
int i = 0;
srandom(getpid()); //设置随机种子
pthread_t tid[6];
//初始化可以卖的商品
ret = sem_init(&sem_customer,0,0);
if(0 != ret)
{
printf("sem_init falied...\n");
}
//初始化可以生产的产品
ret = sem_init(&sem_producer,0,8);
if(0 != ret)
{
printf("sem_init falied...\n");
}
//创建6个线程
for(i = 0; i < 6; i++)
{
//生产者2个
if(i < 2)
{
ret = pthread_create(&tid[i],NULL,producer,NULL);
if(0 != ret)
{
printf("pthread_create failed...\n");
return 1;
}
}
else
{
//消费者4个
ret = pthread_create(&tid[i],NULL,customer,NULL);
if(0 != ret)
{
printf("pthread_create failed...\n");
return 1;
}
}
}
//回收线程资源
for(i=0 ;i<6; i++)
{
pthread_join(tid[i],NULL);
}
//销毁信号变量
sem_destroy(&sem_producer);
sem_destroy(&sem_customer);
return 0;
}
07. 扩展
自旋锁
int pthread_spin_destroy(pthread_spinlock_t *lock);
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
屏障
信号量:
int semget(key_t key, int nsems, int semflg);
08. 练习
哲学家就餐问题参考代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
pthread_mutex_t mutex[5];
void* dine(void* arg)
{
int num = (int)arg;
int left, right;
if(num < 4)
{
// 前4个人,右手拿自己筷子
right = num;
left = num+1;
}
else if(num == 4)
{
// 最后一个人,右手拿别人筷子
right = 0;
left = num;
}
// 吃饭
while(1)
{
// 右手加锁
pthread_mutex_lock(&mutex[right]);
// 尝试抢左手筷子
if(pthread_mutex_trylock(&mutex[left]) == 0)
{
// 吃面。。。
printf("%c 正在吃面。。。。。。\n", num+'A');
// 吃完放筷子
pthread_mutex_unlock(&mutex[left]);
}
// 解锁
pthread_mutex_unlock(&mutex[right]);
sleep(rand()%5);
}
}
int main(int argc, const char* argv[])
{
pthread_t p[5];
for(int i=0; i<5; ++i)
{
pthread_mutex_init(&mutex[i], NULL);
}
for(int i=0; i<5; ++i)
{
pthread_create(&p[i], NULL, dine, (void*)i);
}
for(int i=0; i<5; ++i)
{
pthread_join(p[i], NULL);
}
for(int i=0; i<5; ++i)
{
pthread_mutex_destroy(&mutex[i]);
}
return 0;
}
09. 总结
互斥锁
死锁
读写锁
条件变量
信号量
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)