CSDN|Semaphore 里面居然有这么一个大坑!( 三 )
this.n = n;
this.carName = carName;
this.semaphore = semaphore;
}
@Override
publicvoidrun{
try{
if(semaphore.availablePermits < n) {
System.out.println(Thread.currentThread.getName +"来停车,但是停车位不够了,等着吧");
}
semaphore.acquire(n);
System.out.println(Thread.currentThread.getName +"把自己的"+ carName +"停进来了,剩余停车位:"+ semaphore.availablePermits +"辆");
//模拟停车时长
intparkTime = ThreadLocalRandom.current.nextInt(1,6);
TimeUnit.SECONDS.sleep(parkTime);
System.out.println(Thread.currentThread.getName +"把自己的"+ carName +"开走了,停了"+ parkTime +"小时");
}catch(Exception e) {
e.printStackTrace;
}finally{
semaphore.release(n);
System.out.println(Thread.currentThread.getName +"走后,剩余停车位:"+ semaphore.availablePermits +"辆");
}
}
}
运行后的结果如下(由于是多线程环境 , 运行结果可能不尽相同): 这次这个运行结果和我们预期的是一致的 。 并没有线程阻塞的现象 。那为什么之前的代码就会出现“在运行时 , 有时只会执行完线程A , 其线程B和线程C都静默了”这种现象呢? 是道德的沦丧 , 还是人性的扭曲?我带大家走进代码: 差异就体现在获取剩余通行证的方法上 。 上面是链接里面的代码 , 下面是我自己写的代码 。说实在的 , 链接里面的代码我最开始硬是眼神编译了一分钟 , 没有看出问题来 。当我真正把代码粘到 IDEA 里面 , 跑起来后发现当最先执行了 B 线程后 , A、C 线程都可以执行 。 当最先执行 A 线程的时候 , B、C 线程就不会执行 。我人都懵逼了 , 反复分析 , 发现这和我认知不一样啊!于是我陷入了沉思: 过了一会 , 保洁大爷过来收垃圾 , 问我:“hi , 小帅哥 , 你这瓶红牛喝完了吧?我把瓶子收走了啊 。 ”然后瞟了一眼屏幕 , 指着获取剩余许可证的那行代码对我说:“你这个地方方法调用错了哈 , 你再好好看看方法说明 。 ” System.out.println("剩余可用许可证: " + semaphore.drainPermits); 说完之后 , 拍了拍我的肩膀 , 转身离去 。 得到大师点化 , 我才恍然大悟 。 由于获取剩余可用许可证的方法是 drainPermits , 所以线程 A 调用完成之后 , 剩下的许可证为0 , 然后执行 release 之后 , 许可证变为 1 。 (后面会有对应的方法解释) 这时又是一个公平锁 , 所以 , 如果线程 B 先进去排队了 , 剩下的许可证不足以让 B 线程运行 , 它就一直等着 。 C 线程也就没有机会执行 。把获取剩余可用许可证的方法换为 availablePermits 方法后 , 正常输出: 这真的是一个很小的点 。 所谓当局者迷旁观者清 , 就是这个道理 。
推荐阅读
- 青年|为什么花呗之前要10号还款?里面的套路竟然第一次知道
- 手机使用技巧|手机变慢了,是里面垃圾太多了,那么怎样清理手机垃圾呢?
- 地球|地心的温度,达到了太阳表面的温度,里面会存在着什么物质
- 互联网|购买手机,你是选择实体店还是网上,敢在拼多多里面买手机吗?
- CSDN|三次改变世界、却被无情出局的程序员
- CSDN|机器学习将会如何影响软件开发和测试?看完这文就懂了
- CSDN|语雀的技术架构演进之路
- CSDN|字节跳动、腾讯回应美国政府行政命令;英特尔回应20GB机密文档被泄露;优麒麟20.04.1发布|极客头条
- CSDNTB|监控系统选型,这篇不可不读
- CSDN|知乎技术热帖:Qt 这么强大为什么火不起来?