Linux学习之系统编程篇:使用信号量实现“生产者和消费者模型”

模型中,最为关键的步骤是,在生产者回调函数中,未生产之前,消费者回调函数是阻塞的,阻塞方式是条件变量。
那么不使用条件变量,如何使用“信号量”实现阻塞呢?
答案是因为调用 sem_wait,当 sem == 0 时候,该线程就会阻塞。因此:生产者对应一个信号量 :sem_t produce;消费者对应一个信号量 :sem_t customer。
sem_init(&produce, 0, 2);
sem_init(&customer, 0, 0); 消费者 value = 0,表示被阻塞
Linux学习之系统编程篇:使用信号量实现“生产者和消费者模型”_第1张图片

// 头文件
#include  
#include  
#include 
#include  
#include  
#include  
#include 
sem_t produce; // 定义2个信号量
sem_t custom;
typedef struct node // 定义共享变量结构体
{
 int data;
 struct node* next;
}Node;
Node* phead = NULL; // 头结点置空
// 生产者回调函数
void* produce_fun()
{
 while(1)
 {
 sem_wait(&produce); // 生产者取信号量并生产
 Node* node = (Node*)malloc(sizeof(Node));
 node->data = rand() % 1000;
 node->next = phead;
 phead = node;
 printf("生产者:%lu, 产品:%d\n", pthread_self(), node->data);
 sem_post(&custom); // 给消费者信号量
 sleep(1);
 }
 return NULL; }
// 消费者回调函数
void* custom_fun()
{
 while(1)
 {
 sem_wait(&custom); // 刚开始消费者阻塞,直至生产者给消费者信号量后,解除阻塞
 Node* del = phead; // 记录待删除头结点的位置
 phead = phead->next; // 更新删除后新头结点
 printf("消费者: %lu, 消费: %d\n", pthread_self(), del->data);
 free(del); // 删除头结点
 sem_post(&produce); // 归还信号量,回复阻塞状态
 sleep(1);
 }
 return NULL; }
int main()
{
 srand(time(NULL));
 // 初始化信号量
 sem_init(&produce, 0, 2);
 sem_init(&custom, 0, 0);
 // 创建线程
 pthread_t p1, p2;
 pthread_create(&p1, NULL, produce_fun, NULL);
 pthread_create(&p2, NULL, custom_fun, NULL);
 // 回收子线程
 pthread_join(p1, NULL);
 pthread_join(p2, NULL);
 // 销毁信号量
 sem_destroy(&produce);
 sem_destroy(&custom);
 return 0;
}

你可能感兴趣的:(Linux笔记,信号量,系统编程)