生产者消费者问题:生产者不能在容器满了继续生成,消费者不能在容器为空的时候消费
1.信号量简介
用户进程可以通过操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。信号量是一个变量来表示系统中某种资源的数量。
原语:是一种特殊的程序段,其执行只能一气呵成,不可被中断。
p、v操作
p:
1.s-1
2. s-1>=0进程继续执行
3.s-1<0,进程阻塞进入等待队列,转进程调度
v
1.s+1
2.s+1>0进程继续执行
3.s+1<=0,则从该信号的等待队列中唤醒一等待进程,然后在返回原进程继续执行或转进程调度
2.信号量函数原型
sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
-功能:初始化信号量
-参数:
-sem:信号量变量的地址
-pshared:0用在线程间,非0用在进程间
-value:信号量中的值
sem_destroy
int sem_destroy(sem_t *sem);
-功能:释放资源
sem_wait
int sem_wait(sem_t *sem);
-功能:对信号量加锁,调用一次对信号量的值-1,如果值为0,就阻塞
sem_trywait/sem_timedwait
int sem_trywait(sem_t *sem);
-功能:尝试对信号量加锁,调用一次对信号量的值-1,如果值为0,不阻塞
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
-功能:尝试对信号量加锁,调用一次对信号量的值-1,如果值为0,等待设置的时间
sem_post
int sem_post(sem_t *sem);
功能:对信号量解锁,调用一次对信号量的值+1
3.案例源码
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<semaphore.h>
#include<unistd.h>
//创建一个互斥量
pthread_mutex_t mutex;
//创建两个信号量
sem_t psem;
sem_t csem;
struct Node{
int num;
struct Node *next;
};
struct Node *head;
void *producer(void *arg){
//创建新的节点,添加到链表中
while(1){
sem_wait(&psem);
pthread_mutex_lock(&mutex);
struct Node * newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->next=head;
head=newNode;
newNode->num=rand()%1000;
printf("add node, num %d,tid :%ld\n",newNode->num,pthread_self());
pthread_mutex_unlock(&mutex);
sem_post(&csem);
}
}
void *customer(void *arg){
while(1){
sem_wait(&csem);
pthread_mutex_lock(&mutex);
struct Node *tmp=head;
head=head->next;
printf("del node, num:%d,tid:%ld\n",tmp->num,pthread_self());
free(tmp);
pthread_mutex_unlock(&mutex);
sem_post(&psem);
}
}
//头节点
struct Node * head = NULL;
int main(){
pthread_mutex_init(&mutex,NULL);
sem_init(&psem,0,8);
sem_init(&csem,0,0);
//创建五个生产者线程和五个消费者线程
pthread_t ptids[5],ctids[5];
for(int i=0;i<5;i++){
pthread_create(&ptids[i],NULL,producer,NULL);
pthread_create(&ctids[i],NULL,customer,NULL);
}
for(int i=0;i<5;i++){
pthread_detach(ptids[i]);
pthread_detach(ctids[i]);
}
while(1){
sleep(10);
}
pthread_mutex_destroy(&mutex);
sem_destroy(&psem);
sem_destroy(&csem);
pthread_exit(NULL);
return 0;
}