如果semaphore.acquire()发生InterruptedException,是否需要执行semaphore.release()?

14

从Java的java.util.concurrent.Semaphore文档中,我不太清楚如果semaphore.acquire()阻塞线程并且之后被InterruptedException中断会发生什么。信号量值已经减少了吗?因此需要释放信号量吗?

目前,我正在使用以下代码:

try {
  // use semaphore to limit number of parallel threads
  semaphore.acquire();
  doMyWork();
}
finally {
  semaphore.release();
}

当在acquire()期间发生InterruptedException时,我是否应该避免调用release()呢?

3个回答

13

在acquire()期间发生InterruptedException时,是否应该调用release()?

不应该。如果.acquire()被中断,那么信号量就没有被获取,因此很可能不应该释放它。

您的代码应该为:

// use semaphore to limit number of parallel threads
semaphore.acquire();
try {
  doMyWork();
}
finally {
  semaphore.release();
}

9
问题在于 semaphore.acquire() 方法也会抛出 InterruptedException 异常。 - jblack

8

nos的答案部分正确,除了semaphore.acquire()也会抛出InterruptedException。所以,为了100%正确,代码应该像这样:

try {
    semaphore.acquire();
    try {
        doMyWork();
    } catch (InterruptedException e) { 
        // do something, if you wish
    } finally {
        semaphore.release();
    }
} catch (InterruptedException e) {
    // do something, if you wish
}

1
有必要使用嵌套的try catch吗?我们能否在一个try catch中获取和释放信号量? - Joyce
2
假设您想要优雅地处理当调用semaphore.acquire()抛出InterruptedException的情况,嵌套的try-catch是必要的。在调用semaphore.acquire()期间和已获取后都可能抛出InterruptedException。http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html#acquire() - jblack
我可以使用通用的 Exception e 而不是 InterruptedException e 吗? - Joyce
5
doMyWork() 没有特别的原因会抛出 InterruptedException。当代码不需要等待任何事情并执行非阻塞任务时,不会抛出 InterruptedException。因此,内部的 try 块可以只有一个 finally 子句而没有 catch。 - Nytux

0
如果在线程调用acquire方法之前被中断,或者在等待获取许可证时被中断,将抛出InterruptedException并且不会持有任何许可证,因此无需释放。只有在确定已经获取到许可证(在调用acquire方法后)时,您才需要释放许可证。因此,在您的try块开始之前最好先获取许可证,类似于以下内容:
sem.acquire();
try{
   doMyWork();
}finally{
   sem.release();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接