当前位置:   article > 正文

信号量实现生产者消费者程序_C语言示例

信号量实现生产者消费者程序_C语言示例

信号量的基本思想是通过一个计数器和一组相关的操作来实现资源的控制和同步。计数器表示可用的资源数量,每次访问共享资源时,线程需要先申请信号量,如果信号量的计数器大于零,则线程可以访问共享资源并将计数器减一;如果计数器为零,则线程需要等待,直到其他线程释放资源,使计数器变为非零。
信号量和线程锁Mutex有很多相似之处,也有些不同点:
①Mutex只能是0和1,0表示上锁,1表示释放锁。但是semaphore可以大于1。
②信号量可以用于线程间,也可以用于进程间通信。但是Mutex只能用于线程间通信。
主要有以下几个函数:

int sem_init (sem_t *sem, int pshared, unsigned int value);//初始化信号量
int sem_wait(sem_t *sem); //阻塞等,等不到就一直阻塞着等
int sem_trywait(sem_t *sem); //非阻塞等
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); //定时等
  • 1
  • 2
  • 3
  • 4

生产者消费者模型如下:
创建个仓库,里面有5个空位,可以放0-5件商品。
如果放满了没人来取商品,就是爆仓
如果取货时没货,就是崩盘

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define _POSIX_C_SOURCE 200809L
#include <semaphore.h>

#define NUM 5

int q[NUM];//仓库,最多能放5件物品

sem_t* blank_number;
sem_t* goods_number;

void* producer(void* arg)
{
    int i = 0;
    while(1)
    {
        sem_wait(blank_number);//抢空位,抢不到就一直等
        q[i] = rand() % 100 + 1;
        printf("produce %d\n", q[i]);
        sem_post(goods_number); //增加一个商品
        i = (i + 1) % NUM;
        sleep(rand()%3); //每次休息1-3秒钟
    }
}

void* consumer(void *arg)
{
    int i = 0;
    while(1)
    {
        sem_wait(goods_number);//抢商品,抢不到就阻塞
        printf("consume %d\n", q[i]);
        q[i] = 0; //消费掉这个商品
        sem_post(blank_number);//释放一个空位
        i = (i + 1) % NUM;
        sleep(rand() % 3); //每次休息1-3秒钟
    }
}

int main()
{
//使用time(NULL)函数返回的当前时间作为种子,然后传递给srand函数,以初始化伪随机数生成器。
//通常情况下,如果不给伪随机数生成器提供一个种子,那么每次程序运行时生成的随机数都是相同的。
    srand(time(NULL));

//下面2行是Linux的写法
    // sem_init(blank_number, 0, NUM); //空位,0表示单进程多线程,一开始5个空位
    // sem_init(blank_number, 0, 0); //产品,0表示单进程多线程,一开始0个商品

//下面2行是mac的写法
    blank_number = sem_open("blank_number", O_CREAT, S_IRUSR | S_IWUSR, NUM);
    goods_number = sem_open("goods_number", O_CREAT, S_IRUSR | S_IWUSR, 0);

    pthread_t pid, cid;//生产者ID和消费者ID
    pthread_create(&pid, NULL, producer, NULL); //起生产者线程
    pthread_create(&cid, NULL, consumer, NULL); //起消费者线程

    pthread_join(pid, NULL);
    pthread_join(cid, NULL);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

结果是:

zhanghaodeMacBook-Pro:cpp_excise zhanghao$ ./a.out 
produce 96
produce 85
consume 96
consume 43
consume 18
produce 4
produce 56
produce 64
produce 81
^C
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注:这个代码,可以检测到崩盘:消费如果为0,说明当前没货,就崩盘了。但爆仓检测不到。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/286091
推荐阅读
相关标签
  

闽ICP备14008679号