知识点干货—多线程同步【5】之Semaphore

老子说过,“天下大事必做于细,天下难事必做于易”。人要想有所作为,首先得从细微之处入手,从简单的事情做起。中国前国家队足球教练米卢也曾经说过:“态度决定一切。”,“态度决定一切,细节决定成败”确实是至理名言,在生活中、工作中,学习中,为人处事,都应该端正态度,注重细节,从小事做起,从身边做起。我们只有树立正确的态度,做好了细节,并且坚持下来,才容易成功。

继续总结多线程同步常用的方法或者类,之前介绍了CountDownLatch,CyclicBarriar和Exchanger和Phaser,这次介绍一个比较有名的类–Semaphore,大多数人看到它都不会陌生,但是要问怎么正确的使用它,很多人却回答不上来。

Semaphore–信号量
Semaphore的一个特别典型的应用场景是:线程执行是需要耗费CPU的时间片的,并且占用CPU的资源,例如上下文切换,如果不对线程数量进行控制,CPU工作时同时并发的线程数量可能会非常多,这样就会导致每个线程运行起来非常的缓慢,严重影响到系统的执行效率,它的工作效率将大幅下降。因此,此时我们就可以用信号量来进行控制,从而让CPU能够发挥出最大的效率。

1、定义

Semaphore中文翻译为信号量,它用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用公共资源。在创建Semaphore时会设置令牌,这里的令牌就可以看做允许访问特定资源的线程数量,通过设置它来控制线程数量,这个令牌可能是1,也可能是大于1的任意数字。哪个线程拿到(acquire)了令牌,它就可以去执行了,如果没有令牌则需要等待。 线程执行完毕,一定要归还(release)令牌,否则令牌会被用光,别的线程就无法获得令牌而只能永久等待。

可以这样形象的来理解,
Semaphore对应的功能就类似于公司只有一个厕所,而厕所里仅仅有3个茅坑,如果这时候有10个人都要想上厕所,那么显而易见同时只能有3个人能够占用这些茅坑,其他7个人只能在厕所门口等待,当有人从厕所出来后,才能再进入一个人。

2、常用方法

Semaphore的方法比较多, 我们只介绍一些最常用的方法,有兴趣想深入学习的可以去找相关资料再深入学习。

● Semaphore(int permits)
新建一个Semaphore对象,参数permits是初始化设置许可的数量,即令牌的数量。它表示最多允许permits个线程执行acquire()与release()之间的代码。

● Semaphore(int permits, boolean fair)
新建一个Semaphore对象,参数permits是初始化设置许可的数量,即令牌的数量。参数fair表明创建的Semaphore对象是公平信号量(fair为true)还是非公平信号量(fair为false)。所谓公平信号量表明获得锁的顺序与线程启动的顺序有关,启动早的线程优先获得令牌,但并不代表100%的能够获得信号量,仅仅是在概率上能够优先获得。而非公平信号量就是和公平无关的,线程无论谁先启动,这个参数都无效。

● acquire(int permits)
每调用一次该方法,则消耗permits个许可。

● acquire()
每调用一次该方法,则消耗一个许可。

● release()
每调用一次该方法,相当于许可加1。

● release(int permits)
每调用一次该方法,相当于加上permits个许可。在实际开发中,acquire()与release()成对出现,以保证每个线程用时消耗,用完释放。

● acquireUninterruptibly()
使得等待进入acquile()方法的线程不允许被中断。

● acquireUninterruptibly(int permits)
使得等待进入acquile()方法的线程不允许被中断,且获得锁后,将消耗permits个许可。

● availablePermits()
返回此Semaphore对象当前可用的许可数,此方法通常用于调试,因为许可的数量有可能在实时改变,并不是固定的数量。

● drainPermits()
返回此Semaphore对象当前可用的许可数,并将可用许可清零。

3、演示代码

public class TestSemaphore {
   public static void main(String[] args) {

      // 线程池
      ExecutorService exec = Executors.newCachedThreadPool();

      // 只能3个茅坑同时使用
      final Semaphore semp = new Semaphore(3);

      // 模拟10个人同时访问厕所
      for (int index = 0; index < 10; index++) {
         final int NO = index;

         Runnable run = new Runnable() {
            public void run() {
               try {
                  // 获取空余的茅坑
                  semp.acquire();
                  System.out.println("get a noun: " + NO);
                  Thread.sleep((long) (Math.random() * 10000));

                  //使用完后,释放茅坑
                  semp.release();
                  System.out.println("release,availablePermits : "+semp.availablePermits());
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
            }
         };
         exec.execute(run);
      }
      // 线程池退出
      exec.shutdown();
   }
}

执行结果如下:

get a noun: 0

get a noun: 2

get a noun: 1

release,availablePermits : 0

get a noun: 9

release,availablePermits : 1

get a noun: 8

release,availablePermits : 1

get a noun: 6

release,availablePermits : 1

get a noun: 4

release,availablePermits : 1

get a noun: 3

release,availablePermits : 1

get a noun: 5

release,availablePermits : 1

get a noun: 7

release,availablePermits : 1

4、总结

说实话,本司机开发了十几年程序了,Semaphore使用的情况还真的是很少,可以说几乎没有,但是这也不妨碍我们学习它,对它进行了解,说不定哪天就遇到了使用它的场景,到时我们能够立即想到用它来解决就OK了。另一方面学习它也扩展了我们的知识面,不至于在别人谈论时,我们还不知道它是一个什么东东。

这里写图片描述
本公众号将以推送Android各种技术干货或碎片化知识,以及整理老司机日常工作中踩过的坑涉及到的经验知识为主,也会不定期将正在学习使用的新技术总结出来进行分享。每天一点干货小知识把你的碎片时间充分利用起来。

基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值