POSIX信号量
信号量的类型:sem_t
初始化信号量函数:int sem_init(sem_t* sem,int pthread,unsigned value);
sem:信号量名
pthread:0表示线程间共享,非0表示进程间共享
value:信号量初始值
销毁信号量函数:int sem_destrpy(sem_t* sem);
等待信号量:int sem_wait(sem_t* sem);
发布信号量:int sem_post(sem_t* sem);
生产者与消费者模型
在对临界资源进行加锁的时候可能会产生一个线程不断的生产资源,一个线程却消费资源很慢,或者一个线程消耗资源很快,但是一个线程生产资源很慢。对于这些情况都会造成一些线程的饥饿问题。
生产者和消费者模型是将生产者和消费者平衡,达到生产和消费相对的平衡,这样可以减少线程的饥饿问题。
生产者:向临界资源里面写入数据
消费者:从临界资源里面读出数据
生产者与生产者:互斥关系
消费者与消费者:互斥关系
生产者与消费者:互斥且同步关系
在生产者生产数据达到一定的时候,生产者将阻塞挂起,这时候如果有其他的生产者想要生产数据的时候,必须先申请信号量资源,但是这时候的信号量资源已经饱和,所以只有等待消费者来消费才可以。在生产者之间也可能存在同时访问临界资源,当一个生产者生产到一半的时候,另外一个生产者也来生产,这时候就会产生生产的数据失效的问题。所以在生产者和生产者,消费者与消费者之间需要互斥关系,需要在生产和消费的时候加上互斥锁,这样就可以防止数据失效的存在。
实例:基于链表的生产者消费者模型
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<stdlib.h>
#include<sys/types.h>
typedef struct Node{
int value;
struct Node*next;
}Node;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
sem_t sem_full;
sem_t sem_empty;
void InitList(Node* head){
head->next = NULL;
}
Node* allocNode(int d){
Node* tmp = (Node*)malloc(sizeof(Node));
if(NULL == tmp){
perror("malloc");
exit(1);
}
tmp->value = d;
tmp->next = NULL;
return tmp;
}
void Push(Node* head,int d){
Node* tmp = allocNode(d);
if(NULL == head){
head->next = tmp;
}
tmp->next = head->next;
head->next = tmp;
}
void PopList(Node* head,int *d){
if(NULL == head->next)
return ;
Node* del = head->next;
head->next = del->next;
if(NULL != d)
*d = del->value;
free(del);
}
void DestroyList(Node* head){
if(NULL == head->next)
return ;
while(head->next){
PopList(head,NULL);
}
free(head);
}
void* ShowList(Node*head){
while(head->next){
head = head->next;
printf("%d ",head->value);
}
printf("\n");
}
void* fun_c(void* arg){
Node* head = (Node*)arg;
int i = 0;
while(1){
sem_wait(&sem_empty);
pthread_mutex_lock(&lock);
Push(head,i);
printf("Push data: %d tid = %d\n",i,pthread_self());
sleep(1);
i++;
pthread_mutex_unlock(&lock);
sem_post(&sem_full);
}
}
void* fun_p(void* arg){
Node* head = (Node*)arg;
int i = 0;
while(1){
sem_wait(&sem_full);
pthread_mutex_lock(&lock);
int d = -1;
PopList(head,&d);
printf("Pop data: %d tid = %d\n",d,pthread_self());
sleep(1);
pthread_mutex_unlock(&lock);
sem_post(&sem_empty);
}
}
int main(){
pthread_t t1,t2,t3,t4;
Node head;
int i = 0;
InitList(&head);
sem_init(&sem_empty,0,0);
sem_init(&sem_full,0,10);
pthread_create(&t1,NULL,fun_c,(void*)&head);
pthread_create(&t3,NULL,fun_p,(void*)&head);
pthread_create(&t4,NULL,fun_c,(void*)&head);
pthread_create(&t2,NULL,fun_p,(void*)&head);
pthread_join(t4,NULL);
pthread_join(t3,NULL);
pthread_join(t2,NULL);
pthread_join(t1,NULL);
DestroyList(&head);
sem_destroy(&sem_empty);
sem_destroy(&sem_full);
return 0;
}