尝试锁定未释放资源 (关于IT技术的问题)

4
以下代码已被Fortify标记为违规(锁定的“未发布资源”)
try {
  if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
      //do something
    }
    finally {
       lock.unlock();
   }
}
catch (InterruptedException e) {
  // something
}

能否请您解释一下为什么?在InterruptedException try/catch中,是否应该使用finally语句?我认为内部的try也会处理这种情况。


1
只是 Lock 接口吗? - John Vint
2
我认为这是Fortify的一个bug - 代码看起来很好。 - Boris the Spider
@BoristheSpider 我认为你是正确的。 - John Vint
2个回答

4
Fortify文档描述了“未释放资源漏洞”如下:(链接)

该程序可能无法释放系统资源。

但这不适用于您的示例。如果tryLock返回false或抛出异常,则没有获得锁,try块不会被执行,因此外部try块中不需要finally块来释放任何内容。如果tryLock返回true,则进入内部try块,锁定将在finally中释放。
您所拥有的代码与API文档推荐的方法几乎完全相同。
  Lock lock = ...;
  if (lock.tryLock()) {
      try {
          // manipulate protected state
      } finally {
          lock.unlock();
      }
  } else {
      // perform alternative actions
  }

唯一的区别是你的示例使用了超时的tryLock覆盖,如果超时,则返回false。所以从发布的内容来看,这似乎没问题。

还有一个关键的区别是:局部变量lock。如果 OP 引用的是类成员,那么在持有锁时可能会替换引用。 - shmosel
@shmosel:这是一个有趣的观点。但如果锁被替换了,似乎存在更严重的问题。 - Nathan Hughes
我并不是在暗示它是这样,只是Fortify无法确定。 - shmosel
@shmosel:静态代码分析肯定有其局限性。 - Nathan Hughes

0

我可能有一个不错的解决方案:

long timeout = ...;
Lock someLock = ...;
try {
    if (!someLock.tryLock(timeout, TimeUnit.MILLISECONDS)) {
        // TODO: print some error;
        return;
    }
} catch (InterruptedException e) {
    // TODO: print some error;
    return;
}

try{
    // TODO: Some Logic
} finally {
    someLock.unlock();
}

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