【Linux】多线程 之 信号量

本文详细介绍了Linux中信号量的概念及其在多线程同步与互斥中的应用。通过信号量的计数器和等待队列,可以实现线程间的同步与互斥。同时对比了信号量与条件变量的区别,指出信号量自带条件判断功能,而条件变量需要配合互斥锁使用。文中还提供了使用信号量实现生产者消费者模型的代码示例,强调了在实现过程中对临界资源的保护和正确使用信号量的重要性。
摘要由CSDN通过智能技术生成

信号量

信号量的同步与互斥实现

作用:实现线程或进程之间的同步与互斥
本质:计数器+等待队列+等待与唤醒的功能接口
场景:用于实现进程/线程间的同步与互斥
信号量实现同步:通过自身的计数器进行资源计数,对临界资源访问之前先访问信号量,通过计数判断是否有资源能够访问,若不能访问( 计数<=0 没有资源),则等待,并且计数-1,(如果没有资源了,资源为0,等待并且计数-1,变成-1),当信号量计数器为负值,就说明有多少线程正在等待;若可以访问-计数>0,则计数-1,直接访问;其它线程生产资源促使条件满足后,则判断若计数>0,计数+1(表示没人等待,只把计数+1就可以了,说明此时已经有资源了),否则若计数<0,则唤醒一个等待队列上的线程,并计数+1.(<0说明有人在等待,计数+1,就说明等待的人少了一个)
信号量实现互斥
只需要将计数维持在0/1之间就可以实现互斥

信号量与条件变量实现同步的区别:

条件变量实现同步,没有提供给用户条件判断的功能,是需要用户自己来判断的而信号量本身有计数器,资源计数,有没有资源都是通过计数器来进行资源计数的,通过计数器,我们就能知道有没有资源,能不能访问,跟信号量最大的区别就是条件变量通过自身的计数来实现条件判断
信号量通过自身条件判断实现同步,条件变量是通过用户进行条件判断;并且条件变量使用的是外部用户的条件判断,必须是搭配互斥锁一起使用,而信号量,是通过自身的条件判断,在内部保证了操作的原子性。

信号量的接口函数:

1. 定义信号量: sem_t类型   (sem_t类型的结构体中肯定有 计数器,阻塞队列,等待与唤醒的接口)


2. 初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
信号量变量,(sem_t 结构体至少要有计数器,等待队列,保证计数安全内部有其它的锁)
pshared :标志位,决定了当前的信号量用与进程间还是线程间,0-线程间 ,!0-进程间
(因为是一个库,线程间用全局变量就可以完成,用于进程间(进程间相互独立),实际上申请了一块共享内存,在共享内存中包含了计数器	和共享队列)
信号量的初值(由用户根据资源而定)如果定义的是互斥锁的话,那么初始值就是1,因为互斥是由0和1控制的。
成功0  失败-1


4. 在访问临界资源之前,先访问信号量,判断是否访问: 计数-1
条件判断(有没有资源自给判断)+等待
 int sem_wait(sem_t *sem) ;//若计数<= 0, 则-1后阻塞;否则-1后立即返回  --阻塞函数
  trywait(sem_t *sem)-- 通过自身计数判断是否满足访问条件,不满足则立即报错返回 EINVAL
timedwait(sem_t *sem,const struct timespec* abs_timeout)-- 限制时长的阻塞,超时后报错返回 ETIMEDOUT


5. 促使访问条件满足 + 1, 唤醒阻塞线程/进程
int sem_post(sem_t *sem);	//唤醒信号量等待队列上的线程 且计数+1


6. 销毁信号量
int sem_destroy(sem_t * sem); //销毁信号量

注意: 一个信号量只有一个等待队列,所以我们用信号量实现生产者与消费者模型的时候,需要定义两个信号量实现同步,每一个信号量需要等待在每一个不同的等待队列上。

信号量如何实现同步与互斥

信号量实现同步

厨师做饭的例子:

 sem_t _sem;
 void * food()
 {
   
    int i = 0;
    while(1)
 	{
   
      sem_wait(&_sem); // 没有资源则阻塞等待,有资源则-1访问资源
      
      printf("%d delicious ~~\n",i++);    
  	}
 
    return NULL;
 }
 void* cook()
 {
   
     while(1)
    {
   
       printf("cook ~~\n");
       sleep(1);
       sem_post(&_sem);  //资源+1                                                                                                       
    }
     return NULL;
   }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值