224-C++多线程(信号量)

信号量

在这里插入图片描述
二元信号量:当做互斥量,0,1
在这里插入图片描述
在这里插入图片描述
信号量最大的特点就是PV操作。
P操作是把信号量的值减1,如果减1后的值不小于0,程序继续,如果小于0,阻塞当前的线程。V操作是对信号值加1,如果加1之后是负数,就会唤醒阻塞的线程。信号量的信号值代表的是对资源的获取个数!信号量的值为8,代表有8个资源。我们可以同时有8个线程可以进入。信号量的值为负数,负数的绝对值代表阻塞的线程的个数。初始值代表资源的个数。
我们在V操作的时候,如果信号量的值加1之后大于0,代表没有阻塞的线程。如果加1之后小于0,就是还有阻塞的线程,进行唤醒。
acquire就是减小计数值,相当于P操作
release就是增加计数值,相当于V操作

没有提供函数:获取信号量的值。
为什么没有提供?
因为:没有意义。因为拿信号量跑,有多个线程运行,多个线程循环P操作或者V操作,当你抓住这个线程获取信号量的值,其他线程在跑,在PV操作,你获取的信号量的值只是“抓拍的”而已。只是抓住一个瞬间值而已。

用信号量实现的简单例子

在这里插入图片描述
我们使用个数信号量。
在这里插入图片描述
当前信号量初始值为0。
我们有两种情况
当我们程序进行时,我们有代码区,数据区,堆区,栈区。我们进入主函数,主函数变成主线程,然后创建子线程,线程由栈帧和线程对象的信息构成。继续执行,也有可能是创建的线程也启动了,次序都有可能。‘
第一种情况, 我们创建完子线程,子线程被启动,子线程执行P操作,信号量初始值为0,P操作后,信号量的值为-1,阻塞住,主线程执行,发送信号,然后执行V操作,把阻塞的线程唤醒。有可能主线程继续执行,打印,睡眠。子线程接着向下执行,得到信号,睡眠,执行V操作。
第二种情况。主函数执行,创建子线程,然后执行V操作唤醒线程,V不存在唤醒,把0变为1,睡眠了,子线程跑,执行P操作,减为0,往下执行。
这个函数:被加1之后如果还是小于0,就唤醒线程,如果大于等于0,就不唤醒了。
在这里插入图片描述

用信号量实现三个线程打印ABC

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

如果b线程先运行,对不起,b的信号量为0,P操作变为-1,阻塞住。
如果c线程运行了,对不起,c的信号量为0,P操作为-1,阻塞住。
只有a线程可以接着执行,执行P操作,a的信号量由1变为0,继续执行,打印A,然后V操作,b的信号量由-1变为0,唤醒b线程,然后b线程执行V操作,c的信号量变为0,把c唤醒,c执行V,a执行。

在这里插入图片描述

在这里插入图片描述
C++中,这三种写法都可以
在这里插入图片描述

用信号量完成生产者和消费者

在这里插入图片描述
两种情况
第一种情况:如果先消费,number小于10,进入while,执行P操作,信号量的值0变为-1,阻塞住。生产者线程执行了,指向P操作,信号量的值1变为0,进入执行下去,number+=1,进行V操作,把消费者的信号量的-1变为0,唤醒,如果生产者又回到循环执行,执行P操作,变为-1,阻塞住。消费者被唤醒了,其信号量仍然为0。消费者进行操作,获得资源,然后把生产者唤醒了,再进行消费,0变为-1,阻塞住了。
在这里插入图片描述

运行程序
在这里插入图片描述
如果有2个生产者线程和1个消费者线程,这2个生产者线程能不能并发?能不能同时生产?
在这里插入图片描述
在这里插入图片描述
答案是不能的!因为其中一个生产者线程执行,执行P操作,把1变为0,继续执行下去,另一个生产者线程执行,执行P操作,把0变为-1,阻塞住了!!!这里不能产生并发性!!!

如果把生产者的信号量的值初始化为2时,就可以两个生产者线程并发了,同时生产了!!!
生产者线程1进行,执行P操作,信号量的值2变为1,继续生产。生产者线程2进行,执行P操作,信号量的值1变为0,继续生产。
但是这两个生产者线程同时生产,number+=1很麻烦,线程1+=的过程可能被打断,线程2进行+=1,这就进行了数据的覆盖了。
两个生产者线程进行互相的踩踏!如何防止?加上互斥量。可以同时进入生产,但是改变num的时候,我在改变,你不能改变;你在改变,我不能改变。

注意,拿信号量的值是原子操作,两个线程不会同时拿到信号量的。

用信号量实现队列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5个生产者线程可以同时进行生产吗???
有个问题在这里,生产的时候,要往队里里面放,要看这个队列是否可以同时往里面放,队列里的数据相互侵占,五个线程共享同一个队列资源,我放的时候你不能放。不能真正意义上达到高并发,线程1往里面放,要互斥,线程1放完,其他线程才可以。我们在队列放数据进行了等待。

如何得到高并发呢???
能够把线程互斥掉,互斥掉的同时在线程可以从用户态切换到内核。速度太慢了。我们要在用户态之间解决,所以有无锁队列!(协程库)(无锁队列,epoll底层,k队列)

如果采取下面这种方法呢
在这里插入图片描述
这是线程安全的队列!!!但是,对于这个队列来说很麻烦,生产者在生产的时候,获取了锁,放数据,多个消费者消费的时候,取数据的时候,锁被锁住了,要等待,生产者生产完了,消费者才获取到锁,进行消费。不能满足高并发状态。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值