Linux使用互斥锁和信号量实现生产者消费者模型

问题描述及思路见:使用互斥锁和条件变量实现生产者消费者模型

本文源代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

sem_t semp; //生产者信号量
sem_t semc; //消费者信号量
pthread_mutex_t mutex; //定义互斥锁
 
//定义链表结构体
struct Node
{
	int number;
	struct Node* next;
};
 
//定义头结点
struct Node* head = NULL;
//当前产品总数
int num = 0;
 
//生产者线程函数
void* producer(void* arg)
{
	while(1)
	{
        //判断生产者资源是否为0
        sem_wait(&semp);
        
        //上锁
		pthread_mutex_lock(&mutex);

		struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); //新节点
		newNode->number = rand() % 1000 + 1;
		newNode->next = head; //头插法
		head = newNode;
		num++;
		printf("生产者, id:%ld, number:%d, 剩余产品数:%d\n"
                , pthread_self(), newNode->number, num);
        
        //解锁
		pthread_mutex_unlock(&mutex);
        
        //消费者的资源+1
        sem_post(&semc); 

		sleep(rand() % 3);  //把CPU时间片交给其他线程,不然执行太快了看不到效果
	}
	return NULL;
}
//消费者
void* comsumer(void* arv)
{
	while(1)
	{
        //判断消费者资源是否为0
        sem_wait(&semc);

        //上锁
		pthread_mutex_lock(&mutex);
 
		struct Node* node = head;
		head = head->next; //删头
		num--;
		printf("消费者, id:%ld, number:%d, 剩余产品数:%d\n"
                , pthread_self(), node->number, num);
		free(node);
 
        //解锁
		pthread_mutex_unlock(&mutex);
       
        //消费者资源数+1
        sem_post(&semp);

		sleep(rand() % 3);
	}
	return NULL;
}
int main()
{
    //初始化互斥锁和信号变量
    sem_init(&semp, 0, 10);
    sem_init(&semc, 0, 0);
    pthread_mutex_init(&mutex, NULL);
	
    //创建线程
	pthread_t t1[5], t2[5];
	for (int i = 0; i < 5; i++)
	{
		pthread_create(&t1[i], NULL, producer, NULL);
	}
 
	for (int i = 0; i < 5; i++)
	{
		pthread_create(&t2[i], NULL, comsumer, NULL);
	}
 
	//回收线程资源,由于生产者线程和消费者线程都是死循环,主线程被阻塞在这里了
	for (int i = 0; i < 5; i++)
	{
		pthread_join(t1[i], NULL);
		pthread_join(t2[i], NULL);
	}
 
    //销毁互斥锁和信号变量
	pthread_mutex_destroy(&mutex);
    sem_destroy(&semp);
    sem_destroy(&semc);
	return 0;
}

关键问题:

  1. 两个线程函数对应两个信号量
  2. 如果将生产者信号量初始化为1,说明总资源数为1,这时候不加锁也能实现线程同步,因为生产者和消费者总是只有一个线程能执行
  3. 如果生产者信号量的初始值大于1,就需要对临界资源加互斥锁或者读写锁(本例子中加的互斥锁),否则会有多个生产者或消费者线程同时访问临界资源,造成错误
  4. 如果加了锁,上锁应该在sem_wait之后,解锁应该在sem_post之前,否则会造成死锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值