zoukankan      html  css  js  c++  java
  • 并发编程-semaphore

    semaphore也就是我们常说的信号灯,semaphore可以控制同时访问的线程个数,通过acquire获取一个许可,如果没有就等待,通过release释放一个许可。有点类似限流的作用。叫信号灯的原因也和他的用处有关,比如某商场就5个停车位,每个停车位只能停一辆车,如果这个时候来了10辆车,必须要等前面有空的车位才能进入。

    public class SemaphoreDemo {
    
        //限流(AQS)
    
        //permits; 令牌(5)
    
        //公平和非公平
    
    
        static class Car extends  Thread{
            private int num;
            private Semaphore semaphore;
    
            public Car(int num, Semaphore semaphore) {
                this.num = num;
                this.semaphore = semaphore;
            }
            public void run(){
                try {
                    semaphore.acquire(); //获得一个令牌, 如果拿不到令牌,就会阻塞
                    System.out.println("第"+num+" 抢占一个车位");
                    Thread.sleep(2000);
                    System.out.println("第"+num+" 开走喽");
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            Semaphore semaphore=new Semaphore(5);
            for(int i=0;i<10;i++){
                new Car(i,semaphore).start();
            }
        }
    
    
    
    }

    结果:

    第0 抢占一个车位
    第1 抢占一个车位
    第2 抢占一个车位
    第3 抢占一个车位
    第4 抢占一个车位
    第0 开走喽
    第1 开走喽
    第5 抢占一个车位
    第6 抢占一个车位
    第2 开走喽
    第3 开走喽
    第7 抢占一个车位
    第4 开走喽
    第8 抢占一个车位
    第9 抢占一个车位
    第6 开走喽
    第8 开走喽
    第9 开走喽
    第7 开走喽
    第5 开走喽

    Semaphore源码分析

    从Semaphore的功能来看,我们基本能猜测到它的底层实现一定是基于AQS的共享所,因为需要实现多个线程共享一个领排池

    创建Semaphore 实例的时候,需要一个参数permits,这个基本上可以确定是设置给AQS 的state 的,然后每个线程调用acquire 的时候,执行state = state -1,release 的时候执行state = state + 1,当然,acquire 的时候,如果state = 0,说明没有资源了,需要等待其他线程release。

    Semaphore 分公平策略和非公平策略

    static final class FairSync extends Sync {
         private static final long serialVersionUID = 2014338818796000944L;       
      FairSync(int permits) { super(permits); }

      protected int tryAcquireShared(int acquires) {

    for (;;) { // 区别就在于是不是会先判断是否有线程在排队,然后才进行 CAS 减操作
    if (hasQueuedPredecessors()) return -1;
    int available = getState();
    int remaining = available - acquires;
    if (remaining < 0 || compareAndSetState(available, remaining))

    使用场景

    Semaphore比较常见的就是用来做限流操作了。

  • 相关阅读:
    【学习笔记】斯特林数(未完成)
    【题解/学习笔记】点分树
    【题解】[国家集训队] Crash 的文明世界
    【题解】SP34096 DIVCNTK
    【题解】Loj6053 简单的函数
    【题解】[ZJOI2012]网络
    【题解】bzoj3252 攻略
    【题解】[POI2014]HOT-Hotels 加强版
    IDEA文件夹变红,轻松删除SVN版本控制关联
    配置dataguard broker并主从切换
  • 原文地址:https://www.cnblogs.com/yintingting/p/6641464.html
Copyright © 2011-2022 走看看