【问题标题】:Maximum permit count exceeded : Semaphore超出最大许可计数:信号量
【发布时间】:2017-06-05 16:22:29
【问题描述】:
public class semaphoreTest {

static LinkedList<Integer> integerLinkedList = new LinkedList<>();
static Semaphore semaphore = new Semaphore(1);
static Object lock = new Object();

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                produce();
            } catch (InterruptedException e) {
            }
        }
    });

    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                consume();
            } catch (InterruptedException e) {
            }
        }
    });

    t1.start();
    t2.start();

    t1.join();
    t2.join();

}


private static void produce() throws InterruptedException {
    semaphore.acquire();
    int value = 0;
    while (true) {
        while (integerLinkedList.size() == 10) {
            semaphore.release();
        }

        integerLinkedList.add(value++);


    }

}

private static void consume() throws InterruptedException {
    semaphore.acquire();
    while (true) {
        while (integerLinkedList.size() == 0) {
            semaphore.release();
        }
        //semaphore.release();
        Integer value = integerLinkedList.removeFirst();
        System.out.println("Size of the List is " + integerLinkedList.size() + " and value removed is " + value);
        semaphore.release();

        Thread.sleep(100);
    }
}


}

这是我尝试使用信号量作为锁编写的生产者消费者问题。但我几乎不知道删除了大约 240 个元素后,它给出了一条错误消息,为 Maximum permit count exceeded

我在正确的位置释放锁,但无法弄清楚获取部分的错误。

错误信息如下:

Exception in thread "Thread-0" java.lang.Error: Maximum permit count exceeded
at java.util.concurrent.Semaphore$Sync.tryReleaseShared(Semaphore.java:192)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared(AbstractQueuedSynchronizer.java:1341)
at java.util.concurrent.Semaphore.release(Semaphore.java:426)
at interviewQuestions.semaphoreTest.procude(semaphoreTest.java:53)
at interviewQuestions.semaphoreTest.access$000(semaphoreTest.java:12)
at interviewQuestions.semaphoreTest$1.run(semaphoreTest.java:23)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-1" java.lang.Error: Maximum permit count exceeded
at java.util.concurrent.Semaphore$Sync.tryReleaseShared(Semaphore.java:192)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared(AbstractQueuedSynchronizer.java:1341)
at java.util.concurrent.Semaphore.release(Semaphore.java:426)
at interviewQuestions.semaphoreTest.consume(semaphoreTest.java:72)
at interviewQuestions.semaphoreTest.access$100(semaphoreTest.java:12)
at interviewQuestions.semaphoreTest$2.run(semaphoreTest.java:33)
at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

    标签: java multithreading semaphore


    【解决方案1】:

    问题是您释放信号量的次数多于获得的次数。您应该删除 while 以释放您的信号量。您应该只发布一次,因此请改用 if

    根据你的程序produce()consume()应该变成这个。

    生产()

    private static void produce() throws InterruptedException {       
        int value = 0;      
    
        while (true) {
            //try to get control & put an item.
            semaphore.acquire();
    
            //but if the queue is full, give up and try again.
            if (integerLinkedList.size() == 10) {
                semaphore.release();
                continue;
            }
    
            //if not full, put an item & release the control.
            integerLinkedList.add(value++);
            semaphore.release();
    
        }
    
    }
    

    consume()

    private static void consume() throws InterruptedException {        
        while (true) {
            //try to get the control and consume an item.
            semaphore.acquire();
    
            //but if the queue is empty, give up and try again.
            if (integerLinkedList.size() == 0) {
                semaphore.release();
                continue;
            }
    
            //if not empty, *consume first one, *print it, *release the control and go sleep.
            Integer value = integerLinkedList.removeFirst();
            System.out.println("Size of the List is " + integerLinkedList.size() + " and value removed is " + value);
    
            semaphore.release();    
            Thread.sleep(100);
        }
    }
    

    如果您希望更安全,您可以在每个break; 语句之前添加Thread.sleep(50); 之类的内容,这样您就可以给其他线程一些时间继续执行它。

    我假设您编写了典型的生产者消费者问题。如果你想让我改变什么,请告诉我。无论如何,希望这能解决你的基本问题。 :))

    【讨论】:

      【解决方案2】:

      虽然@Supun 的回答是正确的,但我需要线程无限期地运行。因此我想出了解决方案。

      public void produces() throws InterruptedException {
      
          int value = 0;
          while (true){
              semaphore.acquire();
              if(integerList.size() != 10 ) {
                  integerList.add(value++);
              }
              semaphore.release();
          }
      
      }
      
      public void consumes() throws InterruptedException {
          Thread.sleep(100);
          semaphore.acquire();
          while (true){
              Integer take = integerList.removeFirst();
              System.out.println("Size of the BlockingQueue is : "+ integerList.size()+" and the value consumed is :"+take);
              Thread.sleep(100);
              semaphore.release();
          }
      }
      

      【讨论】:

      • 嗨,实际上我的解决方案可以无限运行。我犯了一个我提到过break的小错误;而不是继续; .您可以看到应该无限运行的 while(true) 在那里。 :)) 我喜欢你的 producer() 方法,因为它非常简单。但是您的 consume() 方法似乎是错误的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多