在前面的“关于多线程同步的初步教程--Metux的设计及使用”一文中,我们讨论了Doug Lea的concurrent包的Mutux的设计及实现,本文讨论一下多线程编程中同样常用的Simaphore的设计和使用。Simaphore也继承于Sync接口,和Mutex相比,Simaphore增加了同步的计数支持。一个Simaphore,代表了多个许可,可以一次获取多个许可,也可以一次释放多个许可。如果将Simaphore的许可数减少到1,那么就可以作为一个Mutex使用了。下面的代码演示了Simaphore的基本使用:
可见,Simaphore是对Mutex的增强,Simaphore也和Mutex相比,增加了如下的方法:
1、public Semaphore(long initialPermits)
构造函数,指定许可的数量。
2、public synchronized long permits()
返回许可的数量。
3、public synchronized void release(long n)
一次释放n个许可。
相应的,在Simaphore的实现中,也增加了一个字段,存储许可的数量:
protected long permits_;
acquire和release方法也有相应的变化:
这些代码都容易理解,特别需要注意的是新增的release(long n)的方法,
其中恢复多个许可,同时,要通过一个循环来notify()其它线程。Simaphore的概念在多线程编程中已经广为熟知,在C++和其它很多语言中也有支持。Doug Lea提供的concurrent包中的Simaphore实现为我们提供了Java中Simaphore的工业强度实现版本,方便了我们在多线程环境中的编程。
- class Pool {
- static final MAX_AVAILABLE = 100; // 100个许可
- private final Semaphore available = new Semaphore(MAX_AVAILABLE);
- public Object getItem() throws InterruptedException { // no synch
- available.acquire();
- return getNextAvailableItem();
- }
- public void putItem(Object x) { // no synch
- if (markAsUnused(x))
- available.release();
- }
- // Not a particularly efficient data structure; just for demo
- protected Object[] items = ... whatever kinds of items being managed
- protected boolean[] used = new boolean[MAX_AVAILABLE];
- protected synchronized Object getNextAvailableItem() {
- for (int i = 0; i < MAX_AVAILABLE; ++i) {
- if (!used[i]) {
- used[i] = true;
- return items[i];
- }
- }
- return null; // not reached
- }
- protected synchronized boolean markAsUnused(Object item) {
- for (int i = 0; i < MAX_AVAILABLE; ++i) {
- if (item == items[i]) {
- if (used[i]) {
- used[i] = false;
- return true;
- }
- else
- return false;
- }
- }
- return false;
- }
- }
可见,Simaphore是对Mutex的增强,Simaphore也和Mutex相比,增加了如下的方法:
1、public Semaphore(long initialPermits)
构造函数,指定许可的数量。
2、public synchronized long permits()
返回许可的数量。
3、public synchronized void release(long n)
一次释放n个许可。
相应的,在Simaphore的实现中,也增加了一个字段,存储许可的数量:
protected long permits_;
acquire和release方法也有相应的变化:
- /** Wait until a permit is available, and take one **/
- public void acquire() throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- synchronized(this) {
- try {
- while (permits_ <= 0) wait();
- --permits_;
- }
- catch (InterruptedException ex) {
- notify();
- throw ex;
- }
- }
- }
- /** Release a permit **/
- public synchronized void release() {
- ++permits_;
- notify();
- }
这些代码都容易理解,特别需要注意的是新增的release(long n)的方法,
- public synchronized void release(long n) {
- if (n < 0) throw new IllegalArgumentException("Negative argument");
- permits_ += n;
- for (long i = 0; i < n; ++i) notify();
- }
其中恢复多个许可,同时,要通过一个循环来notify()其它线程。Simaphore的概念在多线程编程中已经广为熟知,在C++和其它很多语言中也有支持。Doug Lea提供的concurrent包中的Simaphore实现为我们提供了Java中Simaphore的工业强度实现版本,方便了我们在多线程环境中的编程。