一、信号量(信号灯)
(高级的互斥锁)
mutex=1
lock() mutex=0
unlock() mutex=1
mutex实现的同步都是串行的
互斥锁:串行
信号量:并行
1、头文件 - semaphore.h
2、信号量类型
- sem_t sem;
- 加强版的互斥锁【mutex>=1】
3、主要函数
- 初始化信号量
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_timedwait(sem_t *sem,xxxxx);
- 解锁 ++
sem_post(sem_t *sem);
对sem做了++(加加 )操作
4、练习
使用信号量实现生产者、消费者模型
sem_t produce_sem;
sem_t custom_sem;
//节点结构
typedef struct node
{
int data;
struct node* next;
}Node;
//永远指向链表头部指针
Node* head=NULL;
//生产者
void* producer(void* arg)
{
while(1){
sem_wait(&produce_sem); //produce_sem -- ==0,阻塞
//创建一个链表的节点
Node* pnew=(Node*)malloc(sizeof(Node));
//节点初始化
pnew->data=rand()%1000;//0-999
//指针域
pnew->next=head;
head=pnew;
printf("++++++ 生产者:%lu,%d\n",pthread_self(),pnew->data);
sem_post(&custom_sem); //custom_sem++
sleep(rand()%5);
}
return NULL;
}
//消费者
void* customer(void* arg)
{
while(1){
sem_wait(&custom_sem);
//链表不为空,删除一个节点,删除头结点
Node* pdel=head;
head=head->next;
printf("------ 消费者:%lu,%d\n",pthread_self(),pdel->data);
free(pdel);
sem_post(&produce_sem);
sleep(rand()%5);
}
return NULL;
}
int main(int argc,const char* argv[])
{
pthread_t thid[2];
//init
sem_init(&produce_sem,0,4);
sem_init(&custom_sem,0,0);
//创建生产者线程
pthread_create(&thid[0],NULL,producer,NULL);
//创建消费者线程
pthread_create(&thid[1],NULL,customer,NULL);
//阻塞回收子线程
for(int i=0;i<2;++i){
pthread_join(thid[i],NULL);
}
sem_destroy(&produce_sem);
sem_destroy(&custom_sem);
return 0;
}