Semaphore源码分析

Semaphore作用:

以一个停车场运作为例来说明信号量的作用。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦。以后来的车必须在入口等待,直到停车场中有车辆离开。这时,如果有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开一辆,则又可以放入一辆,如此往复。

感觉它的运用方式和线程池有点类似,线程池中一共就那么多个线程,先来的任务先运行,后来的任务如果没有获取到线程资源的话,需要先到阻塞队列中等待,线程空闲了之后再从队列中获取它们运行。

(想到可以用它来控制并发量,给每个任务一个权重,然后获取权重的值,哈哈哈)

 

写个demo测试下:

public class SemaphoreTest {

    static Semaphore semaphore = new Semaphore(1);
    static ThreadPoolExecutor pool = new ThreadPoolExecutor(2,2,0L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));

    public static void main(String[] args) {
        for (int i =0;i<10;i++){
            TestThread temp = new TestThread(String.valueOf(i));
            pool.submit(temp);
        }
        pool.shutdown();
    }

    private static class TestThread implements Runnable{
        private String name ;
        public TestThread(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire(1);
                System.out.println("Thread " + name + " start Run...");
                TimeUnit.SECONDS.sleep(1);
                System.out.println("Thread " + name + " finish...");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
    
}

输出为:

Thread 0 start Run...
Thread 0 finish...
Thread 2 start Run...
Thread 2 finish...
Thread 3 start Run...
Thread 3 finish...
Thread 4 start Run...
Thread 4 finish...
Thread 1 start Run...
Thread 1 finish...
Thread 5 start Run...
Thread 5 finish...
Thread 6 start Run...
Thread 6 finish...
Thread 8 start Run...
Thread 8 finish...
Thread 9 start Run...
Thread 9 finish...
Thread 7 start Run...
Thread 7 finish...

 

接下来分析下它的源码:

首先是构造函数:

 

反正公平和非公平只是最新进来的那个线程是先排队还是先获取锁这一点区别,直接看下非公平的构造函数好了。

Permits称为许可。

 

获取许可acquire():

底层调用的是AQS中的获取共享锁的方法:

获取锁的tryAcquireShared()方法在Semaphore中被重写过的:

感觉这里和ReentrantLock的很像,没有获取到锁的线程会进入AQS的队列排队等待。如果一直没有获取到许可的话,线程会一直等待在这里。

这个if判断有点意思,如果remaingin<0,会直接返回这个负数。然后就会执行到上面的那个d0AcquireSharedInterruptibly()那个方法中,将任务加入队列。

如果remiaing>0,会使用AQS更新state的值,表示获取到许可了。

 

释放许可release():

默认情况下是将state的值加1,当然也可以加大于1的数。

底层还是使用CAS的方式修改state的值:

然后会通知AQS队列中的head节点,让该线程去获取Permits。

 

参考:

http://www.cnblogs.com/nullzx/p/5270233.html(Semaphore解释的比较清楚)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值