zoukankan      html  css  js  c++  java
  • Semaphore用例、源码分析讲解

    semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过 acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。有点类似限流的作用。叫信号灯的原因也和他的用处有关,比如某商场就 5 个停车位,每个停车位只能停一辆车,如果这个时候来了 10 辆车,必须要等前面有空的车位才能进入。
    使用案例
    public static void main(String[] args) {
                Semaphore semaphore=new Semaphore(5);
                for(int i=0;i<10;i++){
                    new Car(i,semaphore).start();
                }
            }
            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+"占用一个停车位");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println("第"+num+"俩车走喽");
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
    使用场景
    Semaphore 比较常见的就是用来做限流操作了。
    Semaphore 源码分析
    从 Semaphore 的功能来看,我们基本能猜测到它的底层实现一定是基于 AQS 的共享所,因为需要实现多个线程共享一个领排池创建 Semaphore 实例的时候,需要一个参数 permits,这个基本上可以确定是设置给 AQS 的 state 的,然后每个线程调用 acquire 的时候,行 state = state - 1,release 的时候执行 state = state + 1,当然,acquire 的时候,如果 state = 0,说明没有资源了,需要等待其他线程 release。
    Semaphore 分公平策略和非公平策略
    FairSync:
    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))
                        return remaining;
                }
            }
        }
    

    NofairSync :

    通过对比发现公平和非公平的区别就在于是否多了一个hasQueuedPredecessors 的判断。
    static final class NonfairSync extends Sync {
            private static final long serialVersionUID = -2694183684443567898L;
    
            NonfairSync(int permits) {
                super(permits);
            }
    
            protected int tryAcquireShared(int acquires) {
                return nonfairTryAcquireShared(acquires);
            }
        }
    
        final int nonfairTryAcquireShared(int acquires) {
            for (; ; ) {
                int available = getState();
                int remaining = available -
                        acquires;
                if (remaining < 0 || compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    
    由于后面的代码和 CountDownLatch 的是完全一样,都是基于共享锁的实现,所以也就没必要再花时间来分析了。
    至此,Semaphore 讲解就结束了,希望朋友们能领悟一些知识。
  • 相关阅读:
    Linux 笔记:文件名
    Linux 一些有用的能力
    理解Linux内核注释
    Linux 的三种软件安装包介绍
    idea 2019 激活
    wget免登陆下载jdk 8u221
    PowerDesigner每点击一次就会提示打印错误对话框
    FormData使用方法详解
    springboot:配置多个数据源
    CSS3绘制不规则图形,代码收集
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13083667.html
Copyright © 2011-2022 走看看