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));
    }


}

 

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

 

源码剖析

结构:

构造方法:

释放方法流程剖析:

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

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

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

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

 这个是Unsafe类里面的方法:

  

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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值