今天讲讲多线程的多位“辅助英雄”:锁、信号量、事件。
多线程示例
在介绍几位多线程方法前,我们先回归下多线程的使用。
在不使用各类方法时,多线程代码的结果为:运行时间为15S(5S为主函数等待时间,10S是子线程运行运行时间),即3个线程是同时运行的。另外,从结果中,可以看到多线程之间是随机运行的,可以说是相当混乱。
缺点:当前多个子线程存在相互抢占资源,会出现同一秒内同时打印hello的情况;另外子线程之间是乱序的,没有先来后到。
注:不知道为什么,微信公众号里设置代码功能不生效,因此只能截图了
锁示例
针对多线程里的锁方法,其实是将第一个子线程在运行时,将其他线程进行上锁,不让他们运行。有点像游乐场里,小朋友们在玩滑梯时,工作人员将他们一个个排队分好,在其中一个小朋友在玩时,其他小朋友不允许进入滑梯。
对应代码如下:
由于thread_demo方法代码是完全一样的,所以我就不再重复复制了。
加入锁后,运行结果为:运行时间为35S(5S为主函数等待时间,10*3 为3个子线程运行的总共时间),因为加入锁后,各子线程成了串行运行。
优点:加入锁后,子线程是依次运行,不再混乱;
缺点:整个程序运行时间将根据子线程数量成倍。
信号量示例
信号量的意思,是在一定线程数量内,允许他们乱序;当超出规定数量后,剩余的线程要进行等待。又比如游乐场里,碰碰车场地里允许10个小朋友同时进入,并由他们随机抢占自己想要的碰碰车;对超过10的小朋友只能等待第二场进入。
示例代码事下:
同样,针对信号量的使用方法,thread_demo方法代码也是一样的。
加入信号量后,运行结果是:总共运行时间是25S(因为信号量是2,即2个子线程是同时运行的,第3个子线程是等他们结束后才运行,所以5+10+10=25);并且信号量里的线程打印hello是乱序的。
优点:加入信号量后,可以适时调整并发线程数量,相当于锁和基础用法之间的中间态;
缺点:当信号量不足时,相当于锁的功能,后续子线程需要等待;当信号量过大时,相当于基础用法,即随机抢占资源。
事件示例
事件的引入,相当于在事件条件发生后才能允许子线程运行。怎么理解呢?比如游乐场里,小朋友们想去玩碰碰车,这时要家长同意。如果家长不同意,即使场地里空无一人,小朋友也不能进行玩。家长同意的动作,即多线程里的事件。
示例代码 如下:
从代码上看,除了hello函数需要做事件启动的判断外,thread_demo需要设置set();在未set()之间,子线程只能wait。
对应结果如下:总共运行时间为15S(5S为主函数等待时间,10S为子线程d的运行时间)。对于a/b/c三个子线程是waiting,当set后,进行hello打印。所以真正运行的只有线程d。
优点:根据不同事件,子线程可以实现不同的功能;相当于水龙头形状,即可以控制热水和冷水。
缺点:当事件发生后,子线程运行和基本用法是一样的,仍然是乱序的。就像家长们同意小朋友们进入游乐场后,小朋友们之间仍然是各自相互抢占。
好啦,锁、信号量、事件的简单使用方法已经介绍完了,希望对大家有所帮助!
作者:华为云特约供稿开发者 鹏哥贼优秀
华为开发者大会 2020(Cloud)将于 2020 年 2 月 11 日 -12 日在深圳举办,这是华为面向 ICT(信息与通信)领域全球开发者的年度顶级旗舰活动。想要了解更多请戳→传送门