JUC学习系列八(信号量 Semaphore)

一个计数信号量。从概念上讲,信号量维护了一个许可集。Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。此类还提供便捷的方法来同时 acquire释放多个许可。小心,在未将公平设置为 true 时使用这些方法会增加不确定延期的风险。

实例:个人感觉信号量类似限流的阀门,控制流量。下面的实例就是控制线程进入的数目

public class SemaphoreTest {

    public void printName(Semaphore sh){
        try {
            sh.acquire();
            System.out.println("当前运行的线程为:"+Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(1);
            sh.release();
        } catch ( Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final Semaphore semaphore=new Semaphore(5,true);
//        final Semaphore semaphore=new Semaphore(5);  //非公平的
        final SemaphoreTest sht=new SemaphoreTest();
        //每次只能进入5个线程,每次等一秒,这里有100个线程,大致是20S的时间
        Long startTime=System.currentTimeMillis();
        for (int i=0;i<100;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sht.printName(semaphore);
                }
            }).start();
        }
        //自旋等待所有线程执行完毕
        // 当前线程组中,主线程存活,另外一个我猜测应该是维护semaphore的线程。
        while (Thread.activeCount()>2){
        }
        Long endTime=System.currentTimeMillis();
        System.out.println("总计:"+(endTime - startTime));
    }


}

 JUC学习系列八(信号量 Semaphore)_第1张图片

上面就是信号量的简单使用方法,下面是API里常用方法,原理和源码后面有时间会补上。

 

JUC学习系列八(信号量 Semaphore)_第2张图片

JUC学习系列八(信号量 Semaphore)_第3张图片

JUC学习系列八(信号量 Semaphore)_第4张图片

源码剖析

结构:

JUC学习系列八(信号量 Semaphore)_第5张图片

构造方法:

JUC学习系列八(信号量 Semaphore)_第6张图片

释放方法流程剖析:

JUC学习系列八(信号量 Semaphore)_第7张图片

JUC学习系列八(信号量 Semaphore)_第8张图片

当操作成功时,信号量会放任此线程通过;当修改操作失败,应该是根据信号量允许进入的值有关,跟State有联系。compareAndSetState()操作涉及到了Unsafe类,这个类的方法全是调用C库的东西。除非有openJDK,不然看不到具体实现。我看不到源码,也不知道这个CAS操作是怎么处理的,走了几次断点,如下:

JUC学习系列八(信号量 Semaphore)_第9张图片

这个是current=3,next=4,CAS操作失败,没有返回true。

JUC学习系列八(信号量 Semaphore)_第10张图片

这个是current=4,next=5,可以看到CAS操作成功了,断点已经走到return那里。

CAS操作是调用AQS里的方法:

JUC学习系列八(信号量 Semaphore)_第11张图片

 这个是Unsafe类里面的方法:

   JUC学习系列八(信号量 Semaphore)_第12张图片

 网上给出的CAS的一些解释:

JUC学习系列八(信号量 Semaphore)_第13张图片

 JUC学习系列八(信号量 Semaphore)_第14张图片

 

你可能感兴趣的:(并发编程)