《java.util.concurrent 包源码阅读》17 信号量 Semaphore
2014-08-26 16:07
525 查看
学过操作系统的朋友都知道信号量,在java.util.concurrent包中也有一个关于信号量的实现:Semaphore。
从代码实现的角度来说,信号量与锁很类似,可以看成是一个有限的共享锁,即只能被有限数量的线程使用的共享锁。
因为存在计数,因此Semaphore的构造函数有参数permits来设定计数:
涉及到线程排队等待的问题,Semaphore也支持fair和unfair模式:
说到线程排队,前面在说“锁”的时候讲过AbstractQueuedSynchronizer,它实现了类似获取锁失败,管理等待的线程的功能。因此信号量的实现同样需要借助这个类。
Sync类使用AbstractQueuedSynchronizer的state来存储信号量的计数:
因为信号量与共享锁类似,因此在获取资源和释放资源的时候使用的都是AbstractQueuedSynchronizer的shared类型的方法。
再次回到前面的unfair和fair模式,这种所谓的公平体现在获取锁的时候:unfair是后来先得,fair是先来先得。来看两者的尝试获取资源的方法:
对于信号量来说,获取资源的过程,就是一个更新资源计数的过程。对于释放资源来说,也是一样。
关于信号量的实现,有了AbstractQueuedSynchronizer和锁的基础,是非常好理解的。
从代码实现的角度来说,信号量与锁很类似,可以看成是一个有限的共享锁,即只能被有限数量的线程使用的共享锁。
因为存在计数,因此Semaphore的构造函数有参数permits来设定计数:
public Semaphore(int permits) { sync = new NonfairSync(permits); }
涉及到线程排队等待的问题,Semaphore也支持fair和unfair模式:
public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); }
说到线程排队,前面在说“锁”的时候讲过AbstractQueuedSynchronizer,它实现了类似获取锁失败,管理等待的线程的功能。因此信号量的实现同样需要借助这个类。
abstract static class Sync extends AbstractQueuedSynchronizer // Unfair模式的实现 static final class NonfairSync extends Sync // Fair模式的实现 static final class FairSync extends Sync
Sync类使用AbstractQueuedSynchronizer的state来存储信号量的计数:
Sync(int permits) { setState(permits); }
因为信号量与共享锁类似,因此在获取资源和释放资源的时候使用的都是AbstractQueuedSynchronizer的shared类型的方法。
再次回到前面的unfair和fair模式,这种所谓的公平体现在获取锁的时候:unfair是后来先得,fair是先来先得。来看两者的尝试获取资源的方法:
// unfair模式 final int nonfairTryAcquireShared(int acquires) { // 直接检查是不是有资源,根本不看前面有没有其他排队的 for (;;) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } } // fair模式 protected int tryAcquireShared(int acquires) { for (;;) { // 先看看有没有排队的 if (hasQueuedPredecessors()) return -1; int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } }
对于信号量来说,获取资源的过程,就是一个更新资源计数的过程。对于释放资源来说,也是一样。
protected final boolean tryReleaseShared(int releases) { for (;;) { int current = getState(); int next = current + releases; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next)) return true; } }
关于信号量的实现,有了AbstractQueuedSynchronizer和锁的基础,是非常好理解的。
相关文章推荐
- 《java.util.concurrent 包源码阅读》20 DelayQueue
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
- 《java.util.concurrent 包源码阅读》22 Fork/Join框架的初体验
- 《java.util.concurrent 包源码阅读》18 Exchanger
- Jdk源码阅读之Java.util.concurrent
- 《java.util.concurrent 包源码阅读》07 LinkedBlockingQueue
- 《java.util.concurrent 包源码阅读》14 线程池系列之ScheduledThreadPoolExecutor 第一部分
- 《java.util.concurrent 包源码阅读》10 线程池系列之AbstractExecutorService
- 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch
- 《java.util.concurrent 包源码阅读》25 Fork/Join框架之Fork与Work-Stealing(重写23,24)
- 《java.util.concurrent 包源码阅读》05 BlockingQueue
- 同步工具类三:计数信号量(java.util.concurrent.Semaphore)
- 《java.util.concurrent 包源码阅读》15 线程池系列之ScheduledThreadPoolExecutor 第二部分
- 《java.util.concurrent 包源码阅读》27 Phaser 第一部分
- 信号量 java.util.concurrent.Semaphore的使用
- 《java.util.concurrent 包源码阅读》01 源码包的结构
- 《java.util.concurrent 包源码阅读》04 ConcurrentMap
- 《java.util.concurrent 包源码阅读》19 PriorityBlockingQueue
- 《java.util.concurrent 包源码阅读》16 一种特别的BlockingQueue:SynchronousQueue
- 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分