经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Java并发(十五):并发工具类——信号量Semaphore
来源:cnblogs  作者:那股泥石流  时间:2018/11/20 10:41:51  对本文有异议

Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。

把它比作是控制流量的红绿灯,比如XX马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶入XX马路,但是如果前一百辆中有五辆车已经离开了XX马路,那么后面就允许有5辆车驶入马路,这个例子里说的车就是线程,驶入马路就表示线程在执行,离开马路就表示线程执行完成,看见红灯就表示线程被阻塞,不能执行。

semaphore实际是允许count个线程同时获取的共享锁。(semaphore = new Semaphore(count); 通过AQS实现,count即state)

semaphore.acquire(); 获取semaphore的锁,state>0:还有数量,可以获取锁;state<=0:线程数量已满,不能获取锁,需要将线程挂起

semaphore.release(); 释放semaphore的锁,就是将state+1 释放成功后,唤醒同步队列中的下一个线程

一、应用举例

  1. /**
  2. * 为了简单起见我们假设停车场仅有5个停车位,一开始停车场没有车辆所有车位全部空着,然后先后到来三辆车,停车场车位够,安排进去停车。
  3. * 然后又来三辆,这个时候由于只有两个停车位,所有只能停两辆,其余一辆必须在外面候着,直到停车场有空车位。
  4. * 当然以后每来一辆都需要在外面候着。当停车场有车开出去,里面有空位了,则安排一辆车进去(至于是哪辆 要看选择的机制是公平还是非公平)。
  5. *
  6. * 从程序角度看,停车场就相当于信号量Semaphore,其中许可数为5,车辆就相对线程。
  7. * 当来一辆车时,许可数就会减 1 ,当停车场没有车位了(许可书 ==0 ),其他来的车辆需要在外面等候着。
  8. * 如果有一辆车开出停车场,许可数 + 1,然后放进来一辆车。
  9. */
  10. class SemaphoreTest {
  11. static class Parking {
  12. // 信号量
  13. private Semaphore semaphore;
  14. Parking(int count) {
  15. semaphore = new Semaphore(count);
  16. }
  17. public void park() {
  18. try {
  19. // 获取信号量
  20. semaphore.acquire();
  21. long time = (long) (Math.random() * 10);
  22. System.out.println(Thread.currentThread().getName() + "进入停车场,停车" + time + "秒...");
  23. Thread.sleep(time);
  24. System.out.println(Thread.currentThread().getName() + "开出停车场...");
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. } finally {
  28. semaphore.release();
  29. }
  30. }
  31. }
  32. static class Car extends Thread {
  33. Parking parking;
  34. Car(Parking parking) {
  35. this.parking = parking;
  36. }
  37. @Override
  38. public void run() {
  39. parking.park(); // 进入停车场
  40. }
  41. }
  42. public static void main(String[] args) {
  43. Parking parking = new Parking(3);
  44. for (int i = 0; i < 5; i++) {
  45. new Car(parking).start();
  46. }
  47. }
  48. /** 输出结果
  49. * Thread-1进入停车场,停车2秒...
  50. * Thread-2进入停车场,停车5秒...
  51. * Thread-0进入停车场,停车3秒...
  52. * Thread-1开出停车场...
  53. * Thread-3进入停车场,停车0秒...
  54. * Thread-3开出停车场...
  55. * Thread-4进入停车场,停车0秒...
  56. * Thread-4开出停车场...
  57. * Thread-0开出停车场...
  58. * Thread-2开出停车场...
  59. */
  60. }

二、类结构

  1. public class Semaphore implements java.io.Serializable {
  2. private final Sync sync;
  3. abstract static class Sync extends AbstractQueuedSynchronizer {}
  4. static final class FairSync extends Sync {}
  5. static final class NonfairSync extends Sync {}
  6. }

三、原理解析

  1. // new Semaphore(count),将AQS的state设置成许可数量count
  2. semaphore = new Semaphore(count);
  3. public Semaphore(int permits) {
  4. sync = new NonfairSync(permits);
  5. }
  6. Sync(int permits) {
  7. setState(permits);
  8. }
  1. /**
  2. * 获取semaphore的锁,
  3. * 获取到锁就可以继续操作,没有获取到锁就进入同步队列挂起
  4. */
  5. semaphore.acquire();
  6. public final void acquireSharedInterruptibly(int arg)
  7. throws InterruptedException {
  8. if (Thread.interrupted())
  9. throw new InterruptedException();
  10. if (tryAcquireShared(arg) < 0)
  11. doAcquireSharedInterruptibly(arg);
  12. }
  13. /**
  14. * state>0:还有数量,可以获取锁
  15. * state<=0:线程数量已满,不能获取锁,需要将线程挂起
  16. */
  17. final int nonfairTryAcquireShared(int acquires) {
  18. for (;;) {
  19. int available = getState();
  20. int remaining = available - acquires;
  21. if (remaining < 0 ||
  22. compareAndSetState(available, remaining))
  23. return remaining;
  24. }
  25. }
  1. /**
  2. * 释放semaphore的锁,就是将state+1
  3. * 释放成功后,唤醒同步队列中的下一个线程
  4. */
  5. semaphore.release();
  6. public void release() {
  7. sync.releaseShared(1);
  8. }
  9. public final boolean releaseShared(int arg) {
  10. if (tryReleaseShared(arg)) {
  11. doReleaseShared();
  12. return true;
  13. }
  14. return false;
  15. }
  16. protected final boolean tryReleaseShared(int releases) {
  17. for (;;) {
  18. int current = getState();
  19. int next = current + releases;
  20. if (next < current) // overflow
  21. throw new Error("Maximum permit count exceeded");
  22. if (compareAndSetState(current, next))
  23. return true;
  24. }
  25. }

 

 

并发工具类(三)控制并发线程数的Semaphore

【死磕Java并发】—–J.U.C之并发工具类:Semaphore

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号