信号量
信号量是进化版的互斥锁,使用信号量可以并发的执行线程,使多个线程间对某一对象的部分数据进行共享,互斥锁只能串行的执行线程。
信号量可以通过不同线程来加锁和解锁。
信号量的相关函数
初始化信号量
sem_init(sem_t *sem,int pshared,unsigned int value);
0-线程同步
1-进程同步
value-最多有几个线程操作共享数据
销毁信号量
sem_destroy(sem_t *sem);
加锁
sem_wait(sem_t *sem);
调用一次相当于对sem做了一次 -- 操作
如果sem值为0,线程会阻塞
尝试加锁
sem_trywait(sem_t *sem);
sem == 0;加锁失败,不阻塞,直接发牛
限时尝试加锁
sem_timewait(sem_t *sem,xxxx);
解锁++
sem_post(sem_t *sem);
对sem做了++ 操作
练习
使用信号量实现生产者,消费者模型。
semxs.c
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#define pvalue 3
#define cvalue 0
sem_t semp;
sem_t semc;
pthread_mutex_t mutex;
int num=0;//用来记录线程池的缓存数量
struct node * head=NULL;
struct node
{
int data;
struct node * next;
};
//生产者线程
void *producter(void * arc)
{
while(1)
{ //加锁,对pvalue信号量进行减操作
sem_wait(&semp);
struct node *pr=(struct node *)malloc(sizeof(struct node));
pr->data=rand()%1000;//产生随机数为0-999
printf("producter pthread data is %d\n",pr->data);
pthread_mutex_lock(&mutex);//互斥锁上锁
num++;
pr->next=head;
head=pr;
printf("p num is %d\n",num);
pthread_mutex_unlock(&mutex);//互斥所解锁
sem_post(&semc);//解锁,对cvalue信号量进行加操作
sleep(rand()%3);
}
}
//消费者线程
void *customer(void * arc)
{
while(1)
{ sem_wait(&semc);//加锁,对cvalue信号量进行减操作
pthread_mutex_lock(&mutex);
num--;
printf("v num is%d\n",num);
struct node * cu=NULL;
cu=head;
head=cu->next;
pthread_mutex_unlock(&mutex);
printf("customer pthread data is %d\n",cu->data);
sem_post(&semp);
free(cu);
cu=NULL;
//sem_post(&semp);//解锁,对pvalue信号量进行加操作
sleep(rand()%5);
}
}
int main()
{
pthread_t id1,id2;
//生产者信号量初始化为3,表示线程池缓存大小为3
sem_init(&semp,0,pvalue);
//消费者信号量初始化为0,表示一开始不能消费
sem_init(&semc,0,cvalue);
pthread_create(&id1,NULL,producter,NULL);
pthread_create(&id2,NULL,customer,NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_mutex_destroy(&mutex);
sem_destroy(&semc);
sem_destroy(&semp);
return 0;
}
设置semp为3和semc为0,这两个配合使用,使线程池的能够储存的数据最多为3个。当生产者生产数据,线程池累计数据,消费者消费线程池里的数据。