我们用条件变量和互斥量实现了生产者消费者之后,也可以试试用信号量。甚至会更加简单。
可能大家对信号量还比较陌生
1.介绍信号量
信号量与互斥量
信号量相当于初始化值为N的互斥量。
互斥量保护了共享数据,但也使并行的线程变成串行,执行效率变低了。
互斥量一次只有一个线程可以访问公共区域,信号量可以同时有N个线程访问共享数据
信号量与信号:信号量(semaphore)和信号(signal)无关,完全是两回事。O(∩_∩)O哈哈~
信号量不只能用于线程中,也可以用于进程间同步。
2.函数用法
首先sem_t sem;定义类型
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
第二个参数,0 代表线程间同步,1代表进程间同步
value即设置初始值,指定同时访问的的线程数
int sem_destroy(sem_t *sem)
sem_wait(sem_t *sem)
可以理解为pthread_mutex_lock
若信号量>0 ,信号量--。 若信号量为0,再调wait阻塞
sem_post(sem_t *sem)
可以理解为pthread_mutex_unlock解锁
做信号量++操作 最多到N,再次++就会阻塞
SPSC.c
#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
int NUM;
sem_t blankNum,productNum;
void *producer(void *arg)
{
int *queue=(int *)arg;
int i=0;
while(1){
sem_wait(&blankNum);//生产将blank--,为0则阻塞
queue[i]=rand()%1000+1;
printf("produce----%d\n",queue[i]);
sem_post(&productNum); //产品++
i=(i+1)%NUM;
sleep(rand()%1);
}
}
void *consumer(void *arg){
int *queue=(int *)arg;
int i=0;
while(1){
sem_wait(&productNum);//消费将产品数--,为零时阻塞等待
printf("consume----%d\n",queue[i]);
queue[i]=0;
sem_post(&blankNum);//将blank++
i=(i+1)%NUM;
sleep(rand()%3);
}
}
int main()
{
printf("The capacity is\n");
scanf("%d",&NUM);
int queue[NUM];//环形队列
pthread_t pid,cid;
sem_init(&blankNum,0,NUM);//初始时blank为NUM
sem_init(&productNum,0,0);//初始时产品为0
pthread_create(&pid,NULL,producer,(void*)queue);
pthread_create(&cid,NULL,consumer,(void*)queue);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
sem_destroy(&blankNum);
sem_destroy(&productNum);
return 0;
}