为什么使用同步时会使用信号量?

时间:2015-10-08 13:33:30

标签: java synchronization semaphore

我正在阅读有关信号量的信息,在代码示例中,当代码使用最终调用的方法进行同步时,为什么会使用信号量。是不是在做同样的事情,即一次限制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

2 个答案:

答案 0 :(得分:4)

Semaphore为您提供了一个线程安全计数器,可以在acquire被调用超出初始限制时阻止。 release可用于撤消acquire

如果对acquire的呼叫成功,则可以保证有足够的容量来保留新项目。

在示例中,有一些循环可以查找免费项目。使用Semaphore可确保在 免费项目之前不会开始这些循环。

synchronized只保证一个线程一次可以执行这部分代码。

答案 1 :(得分:4)

信号量和synchronized块正在执行两个不同的工作。

  • synchronized关键字在访问和变更项数组时保护getNextAvailableItem()。如果一次不限制一个线程,则会损坏的操作。

  • 信号量最多允许100个线程通过,远远超过1.此代码示例的目的是在池为空时阻止对池中对象的请求,然后在此时取消阻塞一个线程一个对象返回到池中。如果没有信号量,事情看起来就像他们一直工作直到游泳池空了。那时请求线程不会阻塞并等待返回一个对象,而是会收到null。