实现信号量版本的生产者和消费者模型(多线程)

举报
xcc-2022 发表于 2022/10/24 21:03:29 2022/10/24
【摘要】 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 实现信号量版本的生产者和消费者模型(多线程)

image-20220927222653276

#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. 练习

哲学家就餐问题参考代码

image-20220927223200301

#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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。