我正在阅读有关信号量的信息,在代码示例中,当代码使用最终调用的方法进行同步时,为什么会使用信号量。是不是在做同样的事情,即一次限制1个线程来执行变异?
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
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;
}
}
我是指调用getItem()调用acquire(),然后调用getNextAvailableItem,但无论如何都会同步。
我错过了什么?
参考:http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html
答案 0 :(得分:4)
Semaphore
为您提供了一个线程安全计数器,可以在acquire
被调用超出初始限制时阻止。 release
可用于撤消acquire
。
如果对acquire
的呼叫成功,则可以保证有足够的容量来保留新项目。
在示例中,有一些循环可以查找免费项目。使用Semaphore
可确保在 免费项目之前不会开始这些循环。
synchronized
只保证一个线程一次可以执行这部分代码。
答案 1 :(得分:4)
信号量和synchronized块正在执行两个不同的工作。
synchronized关键字在访问和变更项数组时保护getNextAvailableItem()。如果一次不限制一个线程,则会损坏的操作。
信号量最多允许100个线程通过,远远超过1.此代码示例的目的是在池为空时阻止对池中对象的请求,然后在此时取消阻塞一个线程一个对象返回到池中。如果没有信号量,事情看起来就像他们一直工作直到游泳池空了。那时请求线程不会阻塞并等待返回一个对象,而是会收到null。